{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "a00f76b64a06a024",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-09-26T00:58:23.682391100Z",
     "start_time": "2024-09-26T00:58:23.618858300Z"
    },
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "from sklearn import metrics\n",
    "import matplotlib.pyplot as plt\n",
    "from sklearn.metrics import roc_auc_score, roc_curve, mean_squared_error,mean_absolute_error, f1_score\n",
    "import lightgbm as lgb\n",
    "import xgboost as xgb\n",
    "from sklearn.ensemble import RandomForestRegressor as rfr\n",
    "from sklearn.linear_model import LinearRegression as lr\n",
    "from sklearn.model_selection import  KFold, StratifiedKFold,GroupKFold, RepeatedKFold\n",
    "import warnings"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "45c3edf9d3acffd9",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-09-26T00:58:26.071768200Z",
     "start_time": "2024-09-26T00:58:23.623884600Z"
    },
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>id</th>\n",
       "      <th>loanAmnt</th>\n",
       "      <th>term</th>\n",
       "      <th>interestRate</th>\n",
       "      <th>installment</th>\n",
       "      <th>grade</th>\n",
       "      <th>subGrade</th>\n",
       "      <th>employmentTitle</th>\n",
       "      <th>employmentLength</th>\n",
       "      <th>homeOwnership</th>\n",
       "      <th>...</th>\n",
       "      <th>n5</th>\n",
       "      <th>n6</th>\n",
       "      <th>n7</th>\n",
       "      <th>n8</th>\n",
       "      <th>n9</th>\n",
       "      <th>n10</th>\n",
       "      <th>n11</th>\n",
       "      <th>n12</th>\n",
       "      <th>n13</th>\n",
       "      <th>n14</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0</td>\n",
       "      <td>35000.0</td>\n",
       "      <td>5</td>\n",
       "      <td>19.52</td>\n",
       "      <td>917.97</td>\n",
       "      <td>E</td>\n",
       "      <td>E2</td>\n",
       "      <td>320.0</td>\n",
       "      <td>2 years</td>\n",
       "      <td>2</td>\n",
       "      <td>...</td>\n",
       "      <td>9.0</td>\n",
       "      <td>8.0</td>\n",
       "      <td>4.0</td>\n",
       "      <td>12.0</td>\n",
       "      <td>2.0</td>\n",
       "      <td>7.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>2.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>1</td>\n",
       "      <td>18000.0</td>\n",
       "      <td>5</td>\n",
       "      <td>18.49</td>\n",
       "      <td>461.90</td>\n",
       "      <td>D</td>\n",
       "      <td>D2</td>\n",
       "      <td>219843.0</td>\n",
       "      <td>5 years</td>\n",
       "      <td>0</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>13.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>2</td>\n",
       "      <td>12000.0</td>\n",
       "      <td>5</td>\n",
       "      <td>16.99</td>\n",
       "      <td>298.17</td>\n",
       "      <td>D</td>\n",
       "      <td>D3</td>\n",
       "      <td>31698.0</td>\n",
       "      <td>8 years</td>\n",
       "      <td>0</td>\n",
       "      <td>...</td>\n",
       "      <td>0.0</td>\n",
       "      <td>21.0</td>\n",
       "      <td>4.0</td>\n",
       "      <td>5.0</td>\n",
       "      <td>3.0</td>\n",
       "      <td>11.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>4.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>3</td>\n",
       "      <td>11000.0</td>\n",
       "      <td>3</td>\n",
       "      <td>7.26</td>\n",
       "      <td>340.96</td>\n",
       "      <td>A</td>\n",
       "      <td>A4</td>\n",
       "      <td>46854.0</td>\n",
       "      <td>10+ years</td>\n",
       "      <td>1</td>\n",
       "      <td>...</td>\n",
       "      <td>16.0</td>\n",
       "      <td>4.0</td>\n",
       "      <td>7.0</td>\n",
       "      <td>21.0</td>\n",
       "      <td>6.0</td>\n",
       "      <td>9.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>4</td>\n",
       "      <td>3000.0</td>\n",
       "      <td>3</td>\n",
       "      <td>12.99</td>\n",
       "      <td>101.07</td>\n",
       "      <td>C</td>\n",
       "      <td>C2</td>\n",
       "      <td>54.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>1</td>\n",
       "      <td>...</td>\n",
       "      <td>4.0</td>\n",
       "      <td>9.0</td>\n",
       "      <td>10.0</td>\n",
       "      <td>15.0</td>\n",
       "      <td>7.0</td>\n",
       "      <td>12.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>4.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>5 rows × 47 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "   id  loanAmnt  term  interestRate  installment grade subGrade  \\\n",
       "0   0   35000.0     5         19.52       917.97     E       E2   \n",
       "1   1   18000.0     5         18.49       461.90     D       D2   \n",
       "2   2   12000.0     5         16.99       298.17     D       D3   \n",
       "3   3   11000.0     3          7.26       340.96     A       A4   \n",
       "4   4    3000.0     3         12.99       101.07     C       C2   \n",
       "\n",
       "   employmentTitle employmentLength  homeOwnership  ...    n5    n6    n7  \\\n",
       "0            320.0          2 years              2  ...   9.0   8.0   4.0   \n",
       "1         219843.0          5 years              0  ...   NaN   NaN   NaN   \n",
       "2          31698.0          8 years              0  ...   0.0  21.0   4.0   \n",
       "3          46854.0        10+ years              1  ...  16.0   4.0   7.0   \n",
       "4             54.0              NaN              1  ...   4.0   9.0  10.0   \n",
       "\n",
       "     n8   n9   n10  n11  n12  n13  n14  \n",
       "0  12.0  2.0   7.0  0.0  0.0  0.0  2.0  \n",
       "1   NaN  NaN  13.0  NaN  NaN  NaN  NaN  \n",
       "2   5.0  3.0  11.0  0.0  0.0  0.0  4.0  \n",
       "3  21.0  6.0   9.0  0.0  0.0  0.0  1.0  \n",
       "4  15.0  7.0  12.0  0.0  0.0  0.0  4.0  \n",
       "\n",
       "[5 rows x 47 columns]"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train_data = pd.read_csv(\"train.csv\")\n",
    "test_data = pd.read_csv(\"testA.csv\")\n",
    "train_data.head(5)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e8e33c8c6d09d83e",
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "source": [
    "## 数据处理"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "da7f9ee0dc218fae",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-09-26T00:58:26.226458200Z",
     "start_time": "2024-09-26T00:58:26.080010300Z"
    },
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1000000, 47)"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 由于等下需要对特征进行变化，因此我先将训练集和测试集堆叠在一起，一起处理才方便，再加入一列作为区分即可。\n",
    "target = train_data[\"isDefault\"]\n",
    "train_data[\"origin\"] = \"train\"\n",
    "test_data[\"origin\"] = \"test\"\n",
    "del train_data[\"isDefault\"]\n",
    "\n",
    "data = pd.concat([train_data, test_data], axis = 0, ignore_index = True)\n",
    "data.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "f23880943d7d1f77",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-09-26T00:58:26.850981300Z",
     "start_time": "2024-09-26T00:58:26.230801400Z"
    },
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "RangeIndex: 1000000 entries, 0 to 999999\n",
      "Data columns (total 47 columns):\n",
      " #   Column              Non-Null Count    Dtype  \n",
      "---  ------              --------------    -----  \n",
      " 0   id                  1000000 non-null  int64  \n",
      " 1   loanAmnt            1000000 non-null  float64\n",
      " 2   term                1000000 non-null  int64  \n",
      " 3   interestRate        1000000 non-null  float64\n",
      " 4   installment         1000000 non-null  float64\n",
      " 5   grade               1000000 non-null  object \n",
      " 6   subGrade            1000000 non-null  object \n",
      " 7   employmentTitle     999999 non-null   float64\n",
      " 8   employmentLength    941459 non-null   object \n",
      " 9   homeOwnership       1000000 non-null  int64  \n",
      " 10  annualIncome        1000000 non-null  float64\n",
      " 11  verificationStatus  1000000 non-null  int64  \n",
      " 12  issueDate           1000000 non-null  object \n",
      " 13  purpose             1000000 non-null  int64  \n",
      " 14  postCode            999999 non-null   float64\n",
      " 15  regionCode          1000000 non-null  int64  \n",
      " 16  dti                 999700 non-null   float64\n",
      " 17  delinquency_2years  1000000 non-null  float64\n",
      " 18  ficoRangeLow        1000000 non-null  float64\n",
      " 19  ficoRangeHigh       1000000 non-null  float64\n",
      " 20  openAcc             1000000 non-null  float64\n",
      " 21  pubRec              1000000 non-null  float64\n",
      " 22  pubRecBankruptcies  999479 non-null   float64\n",
      " 23  revolBal            1000000 non-null  float64\n",
      " 24  revolUtil           999342 non-null   float64\n",
      " 25  totalAcc            1000000 non-null  float64\n",
      " 26  initialListStatus   1000000 non-null  int64  \n",
      " 27  applicationType     1000000 non-null  int64  \n",
      " 28  earliesCreditLine   1000000 non-null  object \n",
      " 29  title               999999 non-null   float64\n",
      " 30  policyCode          1000000 non-null  float64\n",
      " 31  n0                  949619 non-null   float64\n",
      " 32  n1                  949619 non-null   float64\n",
      " 33  n2                  949619 non-null   float64\n",
      " 34  n3                  949619 non-null   float64\n",
      " 35  n4                  958367 non-null   float64\n",
      " 36  n5                  949619 non-null   float64\n",
      " 37  n6                  949619 non-null   float64\n",
      " 38  n7                  949619 non-null   float64\n",
      " 39  n8                  949618 non-null   float64\n",
      " 40  n9                  949619 non-null   float64\n",
      " 41  n10                 958367 non-null   float64\n",
      " 42  n11                 912673 non-null   float64\n",
      " 43  n12                 949619 non-null   float64\n",
      " 44  n13                 949619 non-null   float64\n",
      " 45  n14                 949619 non-null   float64\n",
      " 46  origin              1000000 non-null  object \n",
      "dtypes: float64(33), int64(8), object(6)\n",
      "memory usage: 358.6+ MB\n"
     ]
    }
   ],
   "source": [
    "# 接下来就是对data进行处理，可以先看看其大致的信息：\n",
    "data.info()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "94ef2e3e86bea43e",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-09-26T00:58:27.523149300Z",
     "start_time": "2024-09-26T00:58:26.853969900Z"
    },
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[Text(0, 0, 'employmentTitle'),\n",
       " Text(1, 0, 'postCode'),\n",
       " Text(2, 0, 'title'),\n",
       " Text(3, 0, 'dti'),\n",
       " Text(4, 0, 'pubRecBankruptcies'),\n",
       " Text(5, 0, 'revolUtil'),\n",
       " Text(6, 0, 'n4'),\n",
       " Text(7, 0, 'n10'),\n",
       " Text(8, 0, 'n5'),\n",
       " Text(9, 0, 'n1'),\n",
       " Text(10, 0, 'n2'),\n",
       " Text(11, 0, 'n3'),\n",
       " Text(12, 0, 'n7'),\n",
       " Text(13, 0, 'n6'),\n",
       " Text(14, 0, 'n9'),\n",
       " Text(15, 0, 'n0'),\n",
       " Text(16, 0, 'n14'),\n",
       " Text(17, 0, 'n13'),\n",
       " Text(18, 0, 'n12'),\n",
       " Text(19, 0, 'n8'),\n",
       " Text(20, 0, 'employmentLength'),\n",
       " Text(21, 0, 'n11')]"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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Sr7z9PTM929yUahZFHosiJpFoceCqFkUeiyImkWhx6JSsyj0WBA1i0KPBVXzdipWrJircQ6d1lyqVCk1adJE69evt22zWq1av369WrRokeNjWrRoYTdektatW2cbX7t2bXl7e9uNSUtL008//XTTmgAA4M7i8FtCQ4YMUZ8+fdS0aVPdd999mjp1qi5dumQ7a6h3797y9fVVTEyMJGnw4MFq3bq1pkyZoo4dO2rBggXavn27Zs+eLUmyWCx6+eWXNXHiRAUFBdlOa/bx8VFERET+7SkAACiyHA4skZGRSk1N1euvv67k5GQ1btxYa9asUY0aNSRJiYmJcnP734Gbli1bKjY2VqNHj9bIkSMVFBSk5cuX29ZgkaTXXntNly5d0nPPPadz587pgQce0Jo1a4rEGiylS5fW2LFjs71FVdxrFoUeC6JmUeixIGoWhR4LomZR6LGo1CwKPRZEzaLQY0HVzG8Ww8jNuUQAAACuw7WEAACA6RFYAACA6RFYAACA6RFYAACA6RFYAACA6RFYnJSRkaHNmzdrwYIFkqQLFy7owoULea6bmJh40wtJOiM1NVWfffaZ3nrrLUnS0aNHlZiYmG/171QXL150dQsAcEchsDhhx44dCgoK0iuvvKJ+/fpJkuLi4myL5znj0KFDuu+++9S0aVM98sgjkqQlS5aoT58+Ttf87rvvFBwcrG+++UaTJk2SJCUkJOiFF17IdY2ffvrJ9nFcXNxNb3kxbdo0/frrr5KkrVu3qnbt2goKCtLWrVtzXaNdu3Z65JFHbnvLL3Xr1lVqaqrTj7dardq0aZM+/PBDvf322/rwww+1adMmWa1Wh2sdPXrU7vNly5bp6aefVq9evbRo0SKne7yZzMxMPfTQQ049dsGCBRo8eLBmz55td8V1SXrxxRcdqmUYhj766CO9+uqr+v3333Xq1ClFRkaqadOmGjZsmDIyMhzur1GjRpowYYIOHz7s8GNvZtmyZUpISJB0bRXvfv36ydfXV76+vnr++eedugLunDlz1KpVK1WtWlUeHh66++671aNHD/373/92us+5c+eqbdu2ql69usqWLavq1aurbdu2+vTTT52umZM33nhDly5dcvrxN/5huHfvXq1cuVInT57MU09nz57NcfufX1u5cenSJY0aNUqdO3fWrFmzZBiGXnnlFf31r39V7969ne713LlzGjdunLp06VJgP9eka6+rzZs352vN/MI6LE5o1qyZxowZoyeeeEKVK1fW2bNndfnyZdWpU0cnTpxwquZDDz2krl27asCAAbaaFy5cUIMGDZSUlORUzYYNG2rOnDkKDQ211czIyJCfn1+uXzTBwcHas2ePpGuXUciJxWLRoUOHnOpRkvz9/bVnzx5VrFhRrVq1UmRkpMqXL68ZM2bo559/zlWNefPm5WqcowGwbt26OW4/fPiwatWqpRIlSujAgQMO1dy9e7c6d+4swzAUHBwsT09PpaWlac+ePXJzc9OyZcsUEhKS63rXHy9J//jHPzR+/HgNGjRIbm5u+uCDDzRixAiHw8CtpKenq2zZsrp69apDj3vrrbf06aefqkuXLtq8ebPOnj2r1atXq1atWtn2IzdeffVV/fLLL3Jzc9Pu3bs1cOBANWjQQJmZmZo8ebLatWunt99+26EeS5curYcffljff/+9QkND1bt3bz311FO5vtZJTgICArRr1y5VqVJF0dHRunDhgkaOHCnp2tfEw8Mj189fSRo9erTWrVunwYMHy2q16oMPPlDXrl1VpUoVxcTE6MMPP1T79u0d6nHYsGH69ttv9corrygkJMT2vfjtt9/0/vvvq0OHDrbVy3MrNjY2x+0DBw7UpEmTVLFiRfXo0SPX9bZu3apOnTrp1KlT6t+/v1q0aKG3335bmZmZOnbsmFatWqUHHnjAoR737dunTp066Y8//pC3t7feeust9erVy3a/o89J6dpq7ykpKYqIiNDSpUvl7u6uChUqqHfv3vriiy+UkZGhJUuWOFRTktq3b6+srCx17dpVZcuWtbsvL3/Y/pmzr+9CcdvrOSObypUrG1ar1faxYRhGVlaWUaVKFadrVqpUKVtNq9Vq+9gZVatWzVYzIyPDqFatmtM1C4Knp6dhGIZx5swZo0qVKsbVq1fttrtScHCw8eCDDxqrV682Nm7caGzcuNHYsGGDUaVKFWPp0qXGxo0bHa7ZpEkT46OPPsrxvn/84x/Gvffe61C98uXL2z5u2LCh8dNPP9k+37Fjh1GvXj2He6xdu/ZNbwEBAYabm5vDNQMDA40jR47YPp8yZYpRq1YtY+/evdn2Izd8fHyMc+fOGWfOnDEsFouRkJBgu+/AgQNGQECAwz1WqFDBMAzDOHHihPHee+8Z9957r1GmTBmjW7duxjfffGNkZWU5XLN8+fK257SPj49x6dIl232XLl1y+PVYrVo1IzU11fb58ePHjbvuusswDMOIi4sz/vKXvzjcY9WqVY2UlJQc70tOTnbqZ5vFYjFCQkKMtm3bGm3atLHdSpUqZbRs2dJo27atQ/WaN29urFixwli5cqXh5uZmLFu2zHbf1KlTjVatWjncY7t27Yx33nnHSE9PN9atW2fcddddxujRo233O/qcNIxr35+LFy8ahmEY586dM0qUKGGkpaUZhmEYFy9eNLy8vByuaRjXnpvp6elOPfbP5s2bd9PbP//5T6de34WBwOKEVq1a2V4s14PA8uXLjYcfftjpmk2aNDF+/PFHu5pbtmwxmjdv7nTNjh07GjNmzLCr+dFHHxkRERFO1Xv00Udz3P7444871+D/++tf/2rExsYa48ePN5566inDMAzj9OnTDr2wv/rqK9vHX3755U1vjsrKyjLef/99o2HDhnaP9/b2vukP+NspW7bsTX/wpKenG2XLlnWo3vVfsoZh5Pg1c+aHbuXKlY3PP//c2Lp1a7bbpk2bnPqB5unpme0X/hdffGHUrFnT+Pnnn+32IzcqVqyY48fXObPfOfWwZ88eY/jw4Ya/v79TYb958+bG2rVrDcMwjJCQEOOPP/6w3Xfo0CGjZs2aDtXz9vY2zp8/b/v81KlThp+fn2EY1/7IKVeunMM9VqtWzTh8+HCO9x06dMipX7Lz5883goODjalTp9p935197VSqVMn2cenSpY3MzEzb5+np6U6Fqhv/+DQMw0hNTTWaNWtmvPjii4bVanU6sJw9e9YwDMM4efKk4ebmZgup//3vf42qVas6XNMwDOPhhx829uzZ49Rj/8zNzc1o3bq10b59+2y3Rx55hMBSnOzevdvw9fU1wsPDjdKlSxudOnUyatWqZfz2229O19y4caNRrVo14/nnnzfKlCljDB482PDx8TE2b97sdM3ExESjUaNGRr169Qx3d3ejUaNGRkhIiJGYmOhUvZv9QsnLUSDDMIytW7cazZs3Nx588EHjwIEDhmFcCx09e/bMdY0OHTrYPr7xr7kbb47+RXejlJQU429/+5vxwAMPGNu3bzdq1qzpdGC5//77jXHjxhkZGRl22zMyMozx48cb999/v0P1SpYsabRr184ICwszKlSoYHcUIzU11ahevbrDPT7yyCPG3Llzc7zvypUrhsVicbjmvffea8THx2fbvnz5csPLy8twd3d3qF79+vWNU6dOGYZhGP/617/s7ktMTLT9EnfErX5BWa1W44cffnC45tatWw1/f3/j9ddfN8aMGWPUrl3bGD9+vDFhwgSjTp06xvTp0x2qN3DgQKNt27bGN998Y6xYscJo3bq18dJLLxmGce3IUK1atRzuMSYmxqhVq5YxadIk45tvvjE2bdpkfPPNN8abb75pBAQEGJMnT3a4pmFcO4I0fPhwo3HjxrbQ5mxgqV69uu1I1WOPPWZ335UrV3IMrbdTs2ZNu6NVhmEYaWlpRuvWrY0ePXo4Ff6effZZo2nTpsbo0aON1q1bG926dTN69OhhrF271nj66aeNbt265brWpEmTbLdBgwYZNWvWNAYNGmS3fdKkSQ732LBhQ9v3488uX77s1Ou7MDCHxUmXLl3SypUrlZiYKF9fXz322GPy9PTMU82kpCTFxsbaavbo0UOBgYF5qmkYhn766SclJSXJ19dXoaGhKlGihEM1nnvuOUnX5on8+b3SI0eO6MKFC3meeFtUxMfHa/Dgwdq5c6eOHz+u6tWrO1zj0KFDioqK0t69e1W3bl3b++QHDx7UPffco9jYWNWpUyfX9f48/6FNmzYKCAiQdG3i9bp16/Tuu+861OPevXvl7u6uu+++O8f7jxw5Yvs/HOkzPT3d9ny60fr16zVp0iT98MMPua63YsUKNWvWTDVr1sx236JFi7R//36NHj3aoR779++vjz76yKHH5EZKSoref/99bdu2TceOHVOZMmUUHBysv/3tbwoLC3OoVnp6ut58802tXr1a0rW5DaNGjZKHh4eOHTumgwcPqk2bNg73uHr1an3xxRf6/fffdfHiRZUvX14NGjRQr1699Oijjzpc70YHDhzQyy+/LHd3d23evFn79+93+LXz2GOP6Z133tE999yTY+8TJ050+OdQVFSUWrRooUGDBtltv3Llirp06aLvvvvO4bkcGRkZmj59uo4cOaI+ffro7rvvVv/+/bV79241bdpU77zzjqpVq5arWrk9kWPu3LkO9Thu3DgFBQXlOIcoKytL/fr1c7hmYSCw4LbGjRsnSXrzzTc1atQoXX/KWCwWVa9eXd26dZOXl5fT9a1Wq2bNmqXFixcrNTVVv/32mzZv3qyjR486NCnvupCQEP3222/Ztjdu3Fi/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4bqff/65RowYYbdkvo+Pj2JiYgrkMgBmZLVatW3bNp04cUI+Pj5q1qyZ0wFj7NixWrp0qV599VXVqlVLiYmJmjJlijp37qxx48blc+cAUPB27NihLl26qHr16tq3b58uXLig7777Tv/85z+L/YkZ1xFYnDBx4kSNHj06X2sahqH9+/fr9OnTqlq1qurVq5erdUWKg927d6tz587KzMy0XTbd3d1dS5YsUePGjR2uZxiGPv74Yy1cuNA26TYyMlJ9+/blKAuAIqlZs2YaM2aMnnjiCVWuXFlnz57V5cuXVadOHdNdH66gEFjyIC0tLduKg87O1g4JCdFvv/2WbXvjxo31yy+/OFWzqLj33nv1zDPPaODAgbZtM2fO1Mcff2y78rQj0tPTVbp06fxsEQBcqkqVKjp9+rQsFottvuTVq1dVvXp1nT592tXtFQr+3HTCunXrFBgYqEqVKsnPz8928/f3d7pmTtcpunr1qhITE/PQadHwn//8R/3797fb9vzzz+s///mPU/WqV6+up59+WqtWrVJmZmZ+tAgALhUSEqKvv/7abtvKlSv117/+1UUdFT6OsDihTp06GjFihHr16pXnRXzatWsni8WijRs3qk2bNnb3HT16VIGBgVq9enWe/g+ze+6559S0aVM999xztm0ff/yxfv75Z/3jH/9wuN6RI0f01Vdf6auvvtJ//vMfRUREKDIyUmFhYSpRokR+tg4AheK3335Thw4dFBwcrI0bN6p9+/batWuXVq1apeDgYFe3VygILE6oWrWqUlNT82U+xLx582QYhvr3769Zs2bZtl+fyPvQQw8V+8XOHn74YW3evFm1atWyzWFJSkpSq1at7L7Ga9eudbj2oUOH9NVXX2nBggU6fvy4Tp48mZ+tA0ChuXTpklauXKnExET5+vrqscce08WLF++YheMILE6YMGGCypQpo1dffTXfah4+fNi2LsmdZt68ebka16dPH4fqGoahTZs2aeHChVqyZIl8fX2dmhMDAGaUnp6usmXLsnAcbi4oKEgJCQkqX768qlWrZnefs1cDnjZtmtq0aaNGjRpp69atioqKUsmSJfXZZ5+pRYsW+dH2HWPLli366quvtHjxYlWtWlWRkZGKjIxU3bp1Xd0aAOSb9PR0lSlTRlar1dWtFAoCixNudWVgZ68G7O/vrz179qhixYpq1aqVIiMj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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 最重要的是对缺失值和异常值的处理，那么来看看哪些特征的缺失值和异常值最多：\n",
    "missing = data.isnull().sum() / len(data)\n",
    "missing = missing[missing > 0 ]\n",
    "missing.sort_values(inplace = True)\n",
    "x = np.arange(len(missing))\n",
    "fig, ax = plt.subplots()\n",
    "ax.bar(x,missing)\n",
    "ax.set_xticks(x)\n",
    "ax.set_xticklabels(list(missing.index), rotation = 90, fontsize = \"small\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "5d82b9060b48807d",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-09-26T00:58:27.572144600Z",
     "start_time": "2024-09-26T00:58:27.525142500Z"
    },
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "#  可以发现那些匿名特征的异常值都是很多的，还有employmentLength特征的异常值也很多。后续会进行处理。\n",
    "\n",
    "# 另外，还有很多特征并不是能够直接用来训练的特征，因此需要对其进行处理，比如grade(贷款等级)、subGrade(贷款等级之子级)、employmentLength(就业年限（年）)、issueDate(贷款发放的月份)、earliesCreditLine(借款人最早报告的信用额度开立的月份)\n",
    "# 需要进行预处理."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "ee205992c6795dd",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-09-26T00:58:27.629631500Z",
     "start_time": "2024-09-26T00:58:27.540664500Z"
    },
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['A', 'B', 'C', 'D', 'E', 'F', 'G']\n",
      "['A1', 'A2', 'A3', 'A4', 'A5', 'B1', 'B2', 'B3', 'B4', 'B5', 'C1', 'C2', 'C3', 'C4', 'C5', 'D1', 'D2', 'D3', 'D4', 'D5', 'E1', 'E2', 'E3', 'E4', 'E5', 'F1', 'F2', 'F3', 'F4', 'F5', 'G1', 'G2', 'G3', 'G4', 'G5']\n"
     ]
    }
   ],
   "source": [
    "print(sorted(data['grade'].unique()))\n",
    "print(sorted(data['subGrade'].unique()))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "f1b8ef68ce301e22",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-09-26T00:58:27.633624400Z",
     "start_time": "2024-09-26T00:58:27.601712Z"
    },
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "employmentLength\n",
       "1 year        65671\n",
       "10+ years    328525\n",
       "2 years       90565\n",
       "3 years       80163\n",
       "4 years       59818\n",
       "5 years       62645\n",
       "6 years       46582\n",
       "7 years       44230\n",
       "8 years       45168\n",
       "9 years       37866\n",
       "< 1 year      80226\n",
       "NaN           58541\n",
       "Name: count, dtype: int64"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 那么现在先对employmentLength(就业年限（年）)特征进行处理：  \n",
    "data['employmentLength'].value_counts(dropna=False).sort_index()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "85c54c9faec46a37",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-09-26T00:58:31.190937400Z",
     "start_time": "2024-09-26T00:58:27.634621100Z"
    },
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_40770/537680793.py:2: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method.\n",
      "The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy.\n",
      "\n",
      "For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object.\n",
      "\n",
      "\n",
      "  data[\"employmentLength\"].replace(to_replace=\"10+ years\", value = \"10 years\",\n",
      "/tmp/ipykernel_40770/537680793.py:4: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method.\n",
      "The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy.\n",
      "\n",
      "For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object.\n",
      "\n",
      "\n",
      "  data[\"employmentLength\"].replace(to_replace=\"< 1 year\", value = \"0 years\",\n"
     ]
    }
   ],
   "source": [
    "# 对employmentLength该列进行处理\n",
    "data[\"employmentLength\"].replace(to_replace=\"10+ years\", value = \"10 years\",\n",
    "                                      inplace = True)\n",
    "data[\"employmentLength\"].replace(to_replace=\"< 1 year\", value = \"0 years\",\n",
    "                                      inplace = True)\n",
    "def employmentLength_to_int(s):\n",
    "    if pd.isnull(s):\n",
    "        return s # 如果是nan还是nan\n",
    "    else:\n",
    "        return np.int8(s.split()[0])  # 按照空格分隔得到第一个字符\n",
    "    \n",
    "data[\"employmentLength\"] = data[\"employmentLength\"].apply(employmentLength_to_int)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "6fdd0e9aefc6406e",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-09-26T00:58:31.229087600Z",
     "start_time": "2024-09-26T00:58:31.191934200Z"
    },
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "151504    Oct-2003\n",
       "727557    Sep-1990\n",
       "970457    Feb-1989\n",
       "348829    Aug-2001\n",
       "593443    May-1986\n",
       "Name: earliesCreditLine, dtype: object"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 对earliesCreditLine这个时间列进行处理：\n",
    "data['earliesCreditLine'].sample(5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "bfcca10ad9f72a85",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-09-26T00:58:31.519952500Z",
     "start_time": "2024-09-26T00:58:31.225594700Z"
    },
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "# 只选取年份\n",
    "data[\"earliesCreditLine\"] = data[\"earliesCreditLine\"].apply(lambda x:int(x[-4:]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "bfeaffb2ee6af7a4",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-09-26T00:58:31.549459300Z",
     "start_time": "2024-09-26T00:58:31.521960800Z"
    },
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "earliesCreditLine\n",
       "1944        2\n",
       "1945        1\n",
       "1946        2\n",
       "1949        1\n",
       "1950        7\n",
       "        ...  \n",
       "2011    12282\n",
       "2012     8304\n",
       "2013     4375\n",
       "2014     1863\n",
       "2015      251\n",
       "Name: count, Length: 70, dtype: int64"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data['earliesCreditLine'].value_counts(dropna=False).sort_index()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "61b04086bf5b3555",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-09-26T00:58:31.689651400Z",
     "start_time": "2024-09-26T00:58:31.539954400Z"
    },
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "grade  类型数目为： 7\n",
      "subGrade  类型数目为： 35\n",
      "employmentTitle  类型数目为： 298101\n",
      "homeOwnership  类型数目为： 6\n",
      "verificationStatus  类型数目为： 3\n",
      "purpose  类型数目为： 14\n",
      "postCode  类型数目为： 935\n",
      "regionCode  类型数目为： 51\n",
      "applicationType  类型数目为： 2\n",
      "initialListStatus  类型数目为： 2\n",
      "title  类型数目为： 47903\n",
      "policyCode  类型数目为： 1\n"
     ]
    }
   ],
   "source": [
    "# 对一些类别的特征进行处理，争取将其转换为ont-hot向量\n",
    "cate_features = [\"grade\",\n",
    "                \"subGrade\",\n",
    "                \"employmentTitle\",\n",
    "                \"homeOwnership\",\n",
    "                \"verificationStatus\",\n",
    "                \"purpose\",\n",
    "                \"postCode\",\n",
    "                \"regionCode\",\n",
    "                \"applicationType\",\n",
    "                \"initialListStatus\",\n",
    "                \"title\",\n",
    "                \"policyCode\"]\n",
    "for fea in cate_features:\n",
    "    print(fea, \" 类型数目为：\", data[fea].nunique())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "8baa38f3e22740d1",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-09-26T00:58:31.734788700Z",
     "start_time": "2024-09-26T00:58:31.691995800Z"
    },
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "# 可以看到其中一些特征的类别数目比较少，就适合转换成one-hot向量，但是那些类别数目特别多的就不适合，那么参考baseline采取的做法就是增加计数和排序两类特征"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "3dab9643c5113895",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-09-26T00:58:32.515136400Z",
     "start_time": "2024-09-26T00:58:31.706625600Z"
    },
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "data = pd.get_dummies(data, columns = ['grade', 'subGrade', \n",
    "                                             'homeOwnership', 'verificationStatus', \n",
    "                                             'purpose', 'regionCode'],\n",
    "                     drop_first = True)\n",
    "# drop_first就是k个类别，我只用k-1个来表示，那个没有表示出来的类别就是全0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "4e50ab21088638d5",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-09-26T00:58:33.170020400Z",
     "start_time": "2024-09-26T00:58:32.517204Z"
    },
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "# 高维类别特征需要进行转换\n",
    "for f in ['employmentTitle', 'postCode', 'title']:\n",
    "    # 计算计数\n",
    "    data[f+'_cnts'] = data.groupby([f])['id'].transform('count')\n",
    "    # 计算排名\n",
    "    data[f+'_rank'] = data.groupby([f])['id'].rank(ascending=False)\n",
    "    # 处理NaN值\n",
    "    data[f+'_rank'] = data[f+'_rank'].fillna(0)\n",
    "    # 转换为整数类型\n",
    "    data[f+'_rank'] = data[f+'_rank'].astype(int)\n",
    "    # 删除原始列\n",
    "    del data[f]\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "73a0696587568fc3",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-09-26T00:58:33.184273800Z",
     "start_time": "2024-09-26T00:58:33.171030900Z"
    },
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1000000, 154)"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 处理过后得到的数据为：\n",
    "data.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "21b0849067792f60",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-09-26T00:58:34.058871700Z",
     "start_time": "2024-09-26T00:58:33.221963300Z"
    },
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "# 划分为训练数据和测试数据：\n",
    "train = data[data[\"origin\"] == \"train\"].reset_index(drop=True)\n",
    "test = data[data[\"origin\"] == \"test\"].reset_index(drop=True)\n",
    "features = [f for f in data.columns if f not in ['id','issueDate','isDefault',\"origin\"]]  # 这些特征不用参与训练\n",
    "x_train = train[features]\n",
    "y_train = target\n",
    "x_test = test[features]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "919a4a3f39514697",
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "source": [
    "### 模型训练"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "aab3df1b7cdf5a91",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-09-26T01:12:47.663824700Z",
     "start_time": "2024-09-26T00:58:34.063869800Z"
    },
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "XGBoost score: 0.75221771\n",
      "Feature importances:\n",
      "revolBal: 9712.0\n",
      "annualIncome: 8316.0\n",
      "postCode_cnts: 7817.0\n",
      "employmentTitle_rank: 7479.0\n",
      "loanAmnt: 4915.0\n",
      "n8: 4845.0\n",
      "openAcc: 4292.0\n",
      "employmentLength: 3723.0\n",
      "ficoRangeHigh: 2963.0\n",
      "totalAcc: 2750.0\n",
      "n3: 2454.0\n",
      "postCode_rank: 2052.0\n",
      "n14: 1853.0\n",
      "n2: 1802.0\n",
      "n0: 1572.0\n",
      "pubRec: 1033.0\n",
      "delinquency_2years: 1026.0\n",
      "homeOwnership_1: 968.0\n",
      "title_cnts: 952.0\n",
      "n5: 951.0\n",
      "initialListStatus: 728.0\n",
      "homeOwnership_2: 594.0\n",
      "n13: 572.0\n",
      "grade_E: 506.0\n",
      "regionCode_8: 486.0\n",
      "grade_B: 475.0\n",
      "n11: 426.0\n",
      "regionCode_14: 425.0\n",
      "regionCode_13: 418.0\n",
      "subGrade_C5: 410.0\n",
      "regionCode_21: 405.0\n",
      "subGrade_C2: 396.0\n",
      "purpose_2: 386.0\n",
      "pubRecBankruptcies: 382.0\n",
      "subGrade_D2: 363.0\n",
      "subGrade_D3: 283.0\n",
      "subGrade_C3: 240.0\n",
      "purpose_1: 236.0\n",
      "subGrade_B1: 210.0\n",
      "subGrade_B3: 208.0\n",
      "subGrade_D4: 199.0\n",
      "subGrade_D5: 181.0\n",
      "regionCode_19: 181.0\n",
      "regionCode_18: 176.0\n",
      "subGrade_A2: 169.0\n",
      "regionCode_12: 159.0\n",
      "grade_G: 148.0\n",
      "subGrade_D1: 148.0\n",
      "grade_F: 147.0\n",
      "regionCode_3: 145.0\n",
      "regionCode_22: 144.0\n",
      "regionCode_2: 143.0\n",
      "purpose_10: 140.0\n",
      "regionCode_26: 136.0\n",
      "subGrade_A4: 135.0\n",
      "purpose_9: 130.0\n",
      "subGrade_A3: 129.0\n",
      "regionCode_20: 128.0\n",
      "regionCode_10: 126.0\n",
      "subGrade_E5: 125.0\n",
      "regionCode_5: 125.0\n",
      "regionCode_32: 123.0\n",
      "regionCode_27: 122.0\n",
      "regionCode_36: 122.0\n",
      "subGrade_E1: 120.0\n",
      "subGrade_E2: 118.0\n",
      "purpose_8: 116.0\n",
      "regionCode_42: 111.0\n",
      "regionCode_9: 106.0\n",
      "purpose_7: 97.0\n",
      "regionCode_43: 79.0\n",
      "regionCode_28: 78.0\n",
      "regionCode_15: 74.0\n",
      "subGrade_E3: 70.0\n",
      "regionCode_44: 67.0\n",
      "regionCode_11: 64.0\n",
      "regionCode_39: 64.0\n",
      "regionCode_16: 61.0\n",
      "regionCode_47: 59.0\n",
      "subGrade_F4: 52.0\n",
      "regionCode_33: 50.0\n",
      "subGrade_F1: 49.0\n",
      "regionCode_17: 49.0\n",
      "regionCode_40: 49.0\n",
      "regionCode_29: 48.0\n",
      "subGrade_F2: 46.0\n",
      "subGrade_F3: 44.0\n",
      "regionCode_41: 44.0\n",
      "subGrade_B4: 41.0\n",
      "purpose_11: 40.0\n",
      "regionCode_46: 37.0\n",
      "subGrade_G3: 33.0\n",
      "subGrade_G1: 28.0\n",
      "subGrade_G4: 27.0\n",
      "regionCode_31: 27.0\n",
      "subGrade_G5: 26.0\n",
      "regionCode_48: 26.0\n",
      "n12: 22.0\n",
      "homeOwnership_5: 17.0\n",
      "subGrade_G2: 16.0\n",
      "homeOwnership_3: 13.0\n"
     ]
    }
   ],
   "source": [
    "# 设置 XGBoost 参数\n",
    "xgb_params = {\n",
    "    'booster': 'gbtree',\n",
    "    'objective': 'binary:logistic',\n",
    "    'eval_metric': 'auc',\n",
    "    'gamma': 1,\n",
    "    'min_child_weight': 1.5,\n",
    "    'max_depth': 5,\n",
    "    'lambda': 10,\n",
    "    'subsample': 0.7,\n",
    "    'colsample_bytree': 0.7,\n",
    "    'colsample_bylevel': 0.7,\n",
    "    'eta': 0.04,\n",
    "    'tree_method': 'exact',\n",
    "    'seed': 1,\n",
    "    'nthread': 36,\n",
    "}\n",
    "\n",
    "# 训练 XGBoost 模型\n",
    "dtrain = xgb.DMatrix(x_train, y_train)\n",
    "num_round = 3000\n",
    "xgb_model = xgb.train(params=xgb_params, dtrain=dtrain, num_boost_round=num_round)\n",
    "\n",
    "# 评估模型\n",
    "valid_xgb = xgb_model.predict(xgb.DMatrix(x_train))\n",
    "print(\"XGBoost score: {:<8.8f}\".format(roc_auc_score(y_train, valid_xgb)))\n",
    "\n",
    "# 在测试集上进行预测\n",
    "predict_xgb = xgb_model.predict(xgb.DMatrix(x_test))\n",
    "\n",
    "# 保存预测结果\n",
    "testA = pd.read_csv(\"testA.csv\")\n",
    "testA['isDefault'] = predict_xgb\n",
    "submission_data = testA[['id', 'isDefault']]\n",
    "submission_data.to_csv(\"myresult_xgb.csv\", index=False)\n",
    "\n",
    "# 输出特征重要性\n",
    "feature_importance = xgb_model.get_score(importance_type='weight')  # 可以改为 'gain' 或 'cover'\n",
    "sorted_feature_importance = sorted(feature_importance.items(), key=lambda item: item[1], reverse=True)\n",
    "print(\"Feature importances:\")\n",
    "for feature, importance in sorted_feature_importance:\n",
    "    print(f\"{feature}: {importance}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "2375f0f4-c9e9-49ac-8dc3-57a9b67989c0",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/pengjingwen/.local/lib/python3.10/site-packages/sklearn/linear_model/_logistic.py:469: ConvergenceWarning: lbfgs failed to converge (status=1):\n",
      "STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.\n",
      "\n",
      "Increase the number of iterations (max_iter) or scale the data as shown in:\n",
      "    https://scikit-learn.org/stable/modules/preprocessing.html\n",
      "Please also refer to the documentation for alternative solver options:\n",
      "    https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression\n",
      "  n_iter_i = _check_optimize_result(\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Logistic Regression score: 0.60475432\n",
      "Feature importances:\n",
      "                  Feature    Importance\n",
      "0                loanAmnt  3.618574e-05\n",
      "148         postCode_rank  1.987067e-05\n",
      "145  employmentTitle_cnts  6.282156e-06\n",
      "2            interestRate  1.789669e-06\n",
      "149            title_cnts  4.667730e-07\n",
      "..                    ...           ...\n",
      "147         postCode_cnts -8.982773e-06\n",
      "3             installment -2.030250e-05\n",
      "8            ficoRangeLow -2.362280e-04\n",
      "9           ficoRangeHigh -2.374639e-04\n",
      "18      earliesCreditLine -6.167304e-04\n",
      "\n",
      "[151 rows x 2 columns]\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAA9EAAAK9CAYAAAAjce/mAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABa7klEQVR4nO3dd7QV5f0+7HvTDvUcROkiaEREBUUssYKJBmssiajBgjUaUYktGgtgj4lRY4sRhWissSd2iejXij2oiAZBjEExFhC7sN8/fNk/j7SBIAf1utaatc7MPPPMZ/aczeY+z+yZUrlcLgcAAABYoHp1XQAAAAB8UwjRAAAAUJAQDQAAAAUJ0QAAAFCQEA0AAAAFCdEAAABQkBANAAAABQnRAAAAUJAQDQAAAAUJ0QAAAFCQEA0Ai1GpVCo0jR49us5qOeOMMxa47ciRI+e5/THHHPO11Pvwww9n6NChee+9976W/v8Xs1+PJ554oq5LWWQXXnhhRo4cWddlAHzjNajrAgDg2+SKK66oNX/55ZfnnnvumWN59+7dl0g9W2yxRfbcc89ay3r16lV4+5NOOikrrrhirWVrrLHGYqntqx5++OEMGzYsAwcOTMuWLb+WfXyXXXjhhVluueUycODAui4F4BtNiAaAxWj33XevNf/oo4/mnnvumWP5krLKKqv8T/veaqutss466yzGipa8Dz74IM2aNavrMurMhx9+mKZNm9Z1GQDfGi7nBoAl7IMPPsgRRxyRTp06paqqKt26dcvvfve7lMvlWu1KpVIGDRqUK6+8Mt26dUvjxo3Tu3fvPPDAAwu1v48++igff/zx4jyEijvuuCObbLJJmjVrlhYtWmSbbbbJ888/X6vNP//5zwwcODArrbRSGjdunHbt2mWfffbJ22+/XWkzdOjQHHXUUUmSFVdcsXLp+KRJkzJp0qSUSqW5XopcKpUydOjQWv2USqW88MIL+dnPfpZlllkmG2+8cWX9X/7yl/Tu3TtNmjRJq1atsuuuu+a1115bpGMfOHBgmjdvnsmTJ2fbbbdN8+bN07Fjx1xwwQVJkrFjx+YHP/hBmjVrls6dO+eqq66qtf3sS8QfeOCB/PznP8+yyy6b6urq7Lnnnnn33Xfn2N+FF16Y1VdfPVVVVenQoUMOPvjgOS5979u3b9ZYY408+eST2XTTTdO0adP8+te/TpcuXfL888/n/vvvr7y2ffv2TZK88847OfLII9OjR480b9481dXV2WqrrfLss8/W6nv06NEplUq57rrrcuqpp2b55ZdP48aN88Mf/jD/+te/5qj3sccey9Zbb51lllkmzZo1S8+ePXPuuefWavPiiy/mpz/9aVq1apXGjRtnnXXWya233lqrzWeffZZhw4ala9euady4cZZddtlsvPHGueeeewqdJ4DFzUg0ACxB5XI5P/7xj3Pfffdl3333zVprrZW77rorRx11VF5//fWcffbZtdrff//9ufbaa3PooYemqqoqF154YbbccsuMGTOm0GXVI0eOzIUXXphyuZzu3bvn+OOPz89+9rPC9U6bNi3//e9/ay1bbrnlknxx6fpee+2Vfv365Te/+U0+/PDDXHTRRdl4443z9NNPp0uXLkmSe+65J6+88kr23nvvtGvXLs8//3z+9Kc/5fnnn8+jjz6aUqmUnXbaKS+99FKuvvrqnH322ZV9tG7dOm+99Vbhemfbeeed07Vr15x22mmVP06ceuqpOeGEE9K/f//st99+eeutt3Leeedl0003zdNPP71Il5DPnDkzW221VTbddNOceeaZufLKKzNo0KA0a9Ysxx13XAYMGJCddtopf/zjH7Pnnntmgw02mOPy+EGDBqVly5YZOnRoxo8fn4suuiivvvpqJbQmX/xxYNiwYdl8881z0EEHVdo9/vjjeeihh9KwYcNKf2+//Xa22mqr7Lrrrtl9993Ttm3b9O3bN4ccckiaN2+e4447LknStm3bJMkrr7ySm2++OTvvvHNWXHHFvPnmm7n44ovTp0+fvPDCC+nQoUOtes8444zUq1cvRx55ZKZNm5YzzzwzAwYMyGOPPVZpc88992TbbbdN+/btc9hhh6Vdu3YZN25c/v73v+ewww5Lkjz//PPZaKON0rFjxxxzzDFp1qxZrrvuuuywww654YYbsuOOO1aO/fTTT89+++2X9dZbL9OnT88TTzyRp556KltsscVCnzOA/1kZAPjaHHzwweUvf9zefPPN5STlU045pVa7n/70p+VSqVT+17/+VVmWpJyk/MQTT1SWvfrqq+XGjRuXd9xxxwXue8MNNyyfc8455VtuuaV80UUXlddYY41ykvKFF164wG1HjBhR2f9Xp3K5XH7//ffLLVu2LO+///61tnvjjTfKNTU1tZZ/+OGHc/R/9dVXl5OUH3jggcqy3/72t+Uk5YkTJ9ZqO3HixHKS8ogRI+boJ0l5yJAhlfkhQ4aUk5R32223Wu0mTZpUrl+/fvnUU0+ttXzs2LHlBg0azLF8Xq/H448/Xlm21157lZOUTzvttMqyd999t9ykSZNyqVQqX3PNNZXlL7744hy1zu6zd+/e5U8//bSy/MwzzywnKd9yyy3lcrlcnjp1arlRo0blH/3oR+WZM2dW2p1//vnlJOXLLrussqxPnz7lJOU//vGPcxzD6quvXu7Tp88cyz/++ONa/ZbLX7zmVVVV5ZNOOqmy7L777isnKXfv3r38ySefVJafe+655STlsWPHlsvlcvnzzz8vr7jiiuXOnTuX33333Vr9zpo1q/LzD3/4w3KPHj3KH3/8ca31G264Yblr166VZWuuuWZ5m222maNugLricm4AWIJuv/321K9fP4ceemit5UcccUTK5XLuuOOOWss32GCD9O7duzK/wgorZPvtt89dd92VmTNnzndfDz30UA477LD8+Mc/zoEHHpgnn3wya6yxRn7961/no48+KlTvBRdckHvuuafWlHwx0vjee+9lt912y3//+9/KVL9+/ay//vq57777Kn00adKk8vPHH3+c//73v/n+97+fJHnqqacK1bGwDjzwwFrzN954Y2bNmpX+/fvXqrddu3bp2rVrrXoX1n777Vf5uWXLlunWrVuaNWuW/v37V5Z369YtLVu2zCuvvDLH9gcccECtkeSDDjooDRo0yO23354kuffee/Ppp59m8ODBqVfv//3Xbf/99091dXVuu+22Wv1VVVVl7733Llx/VVVVpd+ZM2fm7bffTvPmzdOtW7e5np+99947jRo1qsxvsskmSVI5tqeffjoTJ07M4MGD5xjdnz2y/s477+Qf//hH+vfvn/fff79yPt5+++3069cvL7/8cl5//fUkX7ymzz//fF5++eXCxwTwdXI5NwAsQa+++mo6dOiQFi1a1Fo++27dr776aq3lXbt2naOPVVZZJR9++GHeeuuttGvXrvC+GzVqlEGDBlUC9Ze/Kzwv66233lxvLDY70PzgBz+Y63bV1dWVn995550MGzYs11xzTaZOnVqr3bRp0wrXvzC+esn0yy+/nHK5PNfXM0mtELswGjdunNatW9daVlNTk+WXX74SGL+8fG7fdf5qTc2bN0/79u0zadKkJP/vd6Jbt2612jVq1CgrrbTSHL8zHTt2rBVyF2TWrFk599xzc+GFF2bixIm1/jiz7LLLztF+hRVWqDW/zDLLJEnl2CZMmJBk/ndx/9e//pVyuZwTTjghJ5xwwlzbTJ06NR07dsxJJ52U7bffPqusskrWWGONbLnlltljjz3Ss2fPwscIsDgJ0QDwHdKpU6ckXwTb/8WsWbOSfPG96LkF+QYN/t9/Mfr375+HH344Rx11VNZaa600b948s2bNypZbblnpZ36+GkZnm99I/JdHv2fXWyqVcscdd6R+/fpztG/evPkC65ibufU1v+Xlr9w87uvw1WNfkNNOOy0nnHBC9tlnn5x88slp1apV6tWrl8GDB8/1/CyOY5vd75FHHpl+/frNtc3KK6+cJNl0000zYcKE3HLLLbn77rszfPjwnH322fnjH/9Y6yoAgCVFiAaAJahz586599578/7779cajX7xxRcr679sbpewvvTSS2natOkcI6BFzL7kdlG2/bLvfe97SZI2bdpk8803n2e7d999N6NGjcqwYcNy4oknVpbP7bjmFZZnj3R+9U7UXx2BXVC95XI5K664YlZZZZXC2y0JL7/8cjbbbLPK/IwZMzJlypRsvfXWSf7f78T48eOz0korVdp9+umnmThx4nxf/y+b1+t7/fXXZ7PNNsull15aa/l7771XucHbwpj9u/Hcc8/Ns7bZx9GwYcNC9bdq1Sp777139t5778yYMSObbrpphg4dKkQDdcJ3ogFgCdp6660zc+bMnH/++bWWn3322SmVStlqq61qLX/kkUdqfS/1tddeyy233JIf/ehH8xwRTDLXO1q///77Oeecc7LccsvV+p71oujXr1+qq6tz2mmn5bPPPpvn/mfX+NVRynPOOWeObWY/y/mrYbm6ujrLLbfcHI/2uvDCCwvXu9NOO6V+/foZNmzYHLWUy+Vaj9ta0v70pz/Veg0vuuiifP7555Xfhc033zyNGjXKH/7wh1q1X3rppZk2bVq22WabQvtp1qzZHK9t8sU5+upr8te//rXyneSFtfbaa2fFFVfMOeecM8f+Zu+nTZs26du3by6++OJMmTJljj6+/Pv71XPTvHnzrLzyyvnkk08WqT6A/5WRaABYgrbbbrtsttlmOe644zJp0qSsueaaufvuu3PLLbdk8ODBlVG82dZYY43069ev1iOukmTYsGHz3c8FF1yQm2++Odttt11WWGGFTJkyJZdddlkmT56cK664YqG+Mzs31dXVueiii7LHHntk7bXXzq677prWrVtn8uTJue2227LRRhvl/PPPT3V1deXxT5999lk6duyYu+++OxMnTpyjz9nB/rjjjsuuu+6ahg0bZrvttkuzZs2y33775Ywzzsh+++2XddZZJw888EBeeumlwvV+73vfyymnnJJjjz02kyZNyg477JAWLVpk4sSJuemmm3LAAQfkyCOP/J9ek0X16aef5oc//GH69++f8ePH58ILL8zGG2+cH//4x0m+uGrg2GOPzbBhw7Llllvmxz/+caXduuuum913373Qfnr37p2LLroop5xySlZeeeW0adMmP/jBD7LtttvmpJNOyt57750NN9wwY8eOzZVXXllr1Hth1KtXLxdddFG22267rLXWWtl7773Tvn37vPjii3n++edz1113Jfnid3TjjTdOjx49sv/++2ellVbKm2++mUceeST//ve/K8+pXm211dK3b9/07t07rVq1yhNPPJHrr78+gwYNWqT6AP5ndXNTcAD4bvjqI67K5S8eD/XLX/6y3KFDh3LDhg3LXbt2Lf/2t7+t9fifcvmLxzcdfPDB5b/85S/lrl27lquqqsq9evUq33fffQvc7913313eYostyu3atSs3bNiw3LJly/KPfvSj8qhRowrVPbdHOs3NfffdV+7Xr1+5pqam3Lhx4/L3vve98sCBA2s9luvf//53eccddyy3bNmyXFNTU955553L//nPf+Z45FO5XC6ffPLJ5Y4dO5br1atX63FXH374YXnfffct19TUlFu0aFHu379/eerUqfN8xNVbb70113pvuOGG8sYbb1xu1qxZuVmzZuVVV121fPDBB5fHjx+/0K/HXnvtVW7WrNkcbfv06VNeffXV51jeuXPnWo9qmt3n/fffXz7ggAPKyyyzTLl58+blAQMGlN9+++05tj///PPLq666arlhw4bltm3blg866KA5HiE1r32Xy188fmybbbYpt2jRopyk8rirjz/+uHzEEUeU27dvX27SpEl5o402Kj/yyCPlPn361Hok1uxHXP31r3+t1e+8HkH24IMPlrfYYotyixYtys2aNSv37NmzfN5559VqM2HChPKee+5Z+T3t2LFjedttty1ff/31lTannHJKeb311iu3bNmy3KRJk/Kqq65aPvXUU2s9FgxgSSqVy0vgDhcAwEIrlUo5+OCD57j0m2+HkSNHZu+9987jjz8+1zugA7B08p1oAAAAKEiIBgAAgIKEaAAAACjId6IBAACgICPRAAAAUJAQDQAAAAU1qOsCoC7NmjUr//nPf9KiRYuUSqW6LgcAAKgj5XI577//fjp06JB69eY93ixE8532n//8J506darrMgAAgKXEa6+9luWXX36e64VovtNatGiR5Is3SnV1dR1XAwAA1JXp06enU6dOlYwwL0I032mzL+Gurq4WogEAgAV+zdONxQAAAKAgIRoAAAAKEqIBAACgICEaAAAAChKiAQAAoCAhGgAAAAoSogEAAKAgIRoAAAAKEqIBAACgICEaAAAAChKiAQAAoCAhGgAAAAoSogEAAKAgIRoAAAAKEqIBAACgICEaAAAAChKiAQAAoCAhGgAAAAoSogEAAKAgIRoAAAAKEqIBAACgICEaAAAAChKiAQAAoCAhGgAAAAoSogEAAKCgBnVdACwN1hhyV+pVNa3rMgAA4Dtj0hnb1HUJi8RINAAAABQkRAMAAEBBQjQAAAAUJEQDAABAQUI0AAAAFCREAwAAQEFCNAAAABQkRAMAAEBBQjQAAAAUJEQDAABAQUI0AAAAFCREAwAAQEFCNAAAABQkRAMAAEBBQjQAAAAUJEQDAABAQUI0AAAAFCREAwAAQEFCNAAAABQkRAMAAEBBQjQAAAAUJEQDAABAQUI0AAAAFCREAwAAQEFCNAAAABQkRAMAAEBBQjQAAAAUJEQDAABAQUI0AAAAFCREAwAAQEFCNAAAABQkRAMAAEBBQjQAAAAUJEQDAABAQUI0AAAAFCREAwAAQEFCNAAAABQkRAMAAEBBQjQAAAAUJEQDAABAQUL0t1Dfvn0zePDgui4DAADgW0eIZrE6/fTTU79+/fz2t79dYvscPXp0SqVS3nvvvSW2TwAA4LtJiGaxuuyyy3L00Ufnsssuq+tSAAAAFjsh+lvu3XffzZ577pllllkmTZs2zVZbbZWXX365sv7tt9/Obrvtlo4dO6Zp06bp0aNHrr766lp99O3bN4ceemiOPvrotGrVKu3atcvQoUPn2Nf999+fjz76KCeddFKmT5+ehx9+uNb6oUOHZq211spll12WFVZYIc2bN88vfvGLzJw5M2eeeWbatWuXNm3a5NRTT621XalUyvDhw7PjjjumadOm6dq1a2699dYkyaRJk7LZZpslSZZZZpmUSqUMHDhwMbxyAAAAcxKiv+UGDhyYJ554IrfeemseeeSRlMvlbL311vnss8+SJB9//HF69+6d2267Lc8991wOOOCA7LHHHhkzZkytfv785z+nWbNmeeyxx3LmmWfmpJNOyj333FOrzaWXXprddtstDRs2zG677ZZLL710jnomTJiQO+64I3feeWeuvvrqXHrppdlmm23y73//O/fff39+85vf5Pjjj89jjz1Wa7thw4alf//++ec//5mtt946AwYMyDvvvJNOnTrlhhtuSJKMHz8+U6ZMybnnnjvP1+OTTz7J9OnTa00AAABFCdHfYi+//HJuvfXWDB8+PJtssknWXHPNXHnllXn99ddz8803J0k6duyYI488MmuttVZWWmmlHHLIIdlyyy1z3XXX1eqrZ8+eGTJkSLp27Zo999wz66yzTkaNGlVZP3369Fx//fXZfffdkyS77757rrvuusyYMaNWP7Nmzcpll12W1VZbLdttt10222yzjB8/Puecc066deuWvffeO926dct9991Xa7uBAwdmt912y8orr5zTTjstM2bMyJgxY1K/fv20atUqSdKmTZu0a9cuNTU183xNTj/99NTU1FSmTp06LfLrCwAAfPcI0d9i48aNS4MGDbL++utXli277LLp1q1bxo0blySZOXNmTj755PTo0SOtWrVK8+bNc9ddd2Xy5Mm1+urZs2et+fbt22fq1KmV+auvvjrf+973suaaayZJ1lprrXTu3DnXXnttre26dOmSFi1aVObbtm2b1VZbLfXq1au17Mt9f3X/zZo1S3V19Rxtijj22GMzbdq0yvTaa68tdB8AAMB3V4O6LoC69dvf/jbnnntuzjnnnPTo0SPNmjXL4MGD8+mnn9Zq17Bhw1rzpVIps2bNqsxfeumlef7559Ogwf/7lZo96rzvvvvOt58F9V1k/0VVVVWlqqpqobcDAABIhOhvte7du+fzzz/PY489lg033DDJFzcSGz9+fFZbbbUkyUMPPZTtt9++chn2rFmz8tJLL1XWFzF27Ng88cQTGT16dOXS6iR555130rdv37z44otZddVVF+OR1daoUaMkX4yqAwAAfJ1czv0t1rVr12y//fbZf//98+CDD+bZZ5/N7rvvno4dO2b77bevtLnnnnvy8MMPZ9y4cfn5z3+eN998c6H2c+mll2a99dbLpptumjXWWKMybbrppll33XXneoOxxalz584plUr5+9//nrfeemuO72EDAAAsLkL0t9yIESPSu3fvbLvtttlggw1SLpdz++23Vy6PPv7447P22munX79+6du3b9q1a5cddtihcP+ffvpp/vKXv+QnP/nJXNf/5Cc/yeWXX165G/jXoWPHjhk2bFiOOeaYtG3bNoMGDfra9gUAAHy3lcrlcrmui4C6Mn369C/u0j34utSralrX5QAAwHfGpDO2qesSapmdDaZNm5bq6up5tjMSDQAAAAUJ0QAAAFCQEA0AAAAFCdEAAABQkBANAAAABQnRAAAAUJAQDQAAAAUJ0QAAAFCQEA0AAAAFCdEAAABQkBANAAAABQnRAAAAUJAQDQAAAAUJ0QAAAFCQEA0AAAAFCdEAAABQkBANAAAABQnRAAAAUJAQDQAAAAUJ0QAAAFCQEA0AAAAFCdEAAABQkBANAAAABQnRAAAAUJAQDQAAAAUJ0QAAAFCQEA0AAAAFCdEAAABQkBANAAAABQnRAAAAUJAQDQAAAAUJ0QAAAFCQEA0AAAAFCdEAAABQkBANAAAABQnRAAAAUJAQDQAAAAUJ0QAAAFCQEA0AAAAFCdEAAABQUIO6LgCWBs8N65fq6uq6LgMAAFjKGYkGAACAgoRoAAAAKEiIBgAAgIKEaAAAAChIiAYAAICChGgAAAAoSIgGAACAgoRoAAAAKEiIBgAAgIKEaAAAAChIiAYAAICChGgAAAAoSIgGAACAgoRoAAAAKEiIBgAAgIKEaAAAAChIiAYAAICChGgAAAAoSIgGAACAgoRoAAAAKEiIBgAAgIKEaAAAACioQV0XAEuDNYbclXpVTeu6DAC+4SadsU1dlwDA18xINAAAABQkRAMAAEBBQjQAAAAUJEQDAABAQUI0AAAAFCREAwAAQEFCNAAAABQkRAMAAEBBQjQAAAAUJEQDAABAQUI0AAAAFCREAwAAQEFCNAAAABQkRAMAAEBBQjQAAAAUJEQDAABAQUI0AAAAFCREAwAAQEFCNAAAABQkRAMAAEBBQjQAAAAUJEQDAABAQUI0AAAAFCREAwAAQEFCNAAAABQkRAMAAEBBQjQAAAAUJEQDAABAQUI0AAAAFCREAwAAQEFCNAAAABQkRAMAAEBBQjQAAAAUJEQDAABAQUI0AAAAFCREAwAAQEFCNAAAABQkRAMAAEBBQjQAAAAUJEQDAABAQUI0AAAAFCREM4ehQ4dmrbXWqusyCimVSrn55pvrugwAAOA7Qoheyo0ePTqlUinvvffeHOveeOONHHLIIVlppZVSVVWVTp06ZbvttsuoUaOWfKEAAADfAQ3qugAWzaRJk7LRRhulZcuW+e1vf5sePXrks88+y1133ZWDDz44L774Yl2XOE+fffZZGjZsWNdlAAAALDQj0YtB3759M2jQoAwaNCg1NTVZbrnlcsIJJ6RcLidJ3n333ey5555ZZpll0rRp02y11VZ5+eWXK9u/+uqr2W677bLMMsukWbNmWX311XP77bdn0qRJ2WyzzZIkyyyzTEqlUgYOHJgk+cUvfpFSqZQxY8bkJz/5SVZZZZWsvvrqOfzww/Poo49W+p48eXK23377NG/ePNXV1enfv3/efPPNWvWfccYZadu2bVq0aJF99903H3/88RzHOHz48HTv3j2NGzfOqquumgsvvLDQazNp0qSUSqVce+216dOnTxo3bpwrr7wyb7/9dnbbbbd07NgxTZs2TY8ePXL11VfP8boeeuihOfroo9OqVau0a9cuQ4cOne/+hgwZkvbt2+ef//xnofoAAAAWhhC9mPz5z39OgwYNMmbMmJx77rn5/e9/n+HDhydJBg4cmCeeeCK33nprHnnkkZTL5Wy99db57LPPkiQHH3xwPvnkkzzwwAMZO3ZsfvOb36R58+bp1KlTbrjhhiTJ+PHjM2XKlJx77rl55513cuedd+bggw9Os2bN5qilZcuWSZJZs2Zl++23zzvvvJP7778/99xzT1555ZXssssulbbXXXddhg4dmtNOOy1PPPFE2rdvP0dAvvLKK3PiiSfm1FNPzbhx43LaaaflhBNOyJ///OfCr88xxxyTww47LOPGjUu/fv3y8ccfp3fv3rntttvy3HPP5YADDsgee+yRMWPGzPG6NmvWLI899ljOPPPMnHTSSbnnnnvm6L9cLueQQw7J5Zdfnv/7v/9Lz54951rHJ598kunTp9eaAAAAinI592LSqVOnnH322SmVSunWrVvGjh2bs88+O3379s2tt96ahx56KBtuuGGSL0Jpp06dcvPNN2fnnXfO5MmT85Of/CQ9evRIkqy00kqVflu1apUkadOmTSUcjxkzJuVyOauuuup8axo1alTGjh2biRMnplOnTkmSyy+/PKuvvnoef/zxrLvuujnnnHOy7777Zt99902SnHLKKbn33ntrjUYPGTIkZ511VnbaaackyYorrpgXXnghF198cfbaa69Cr8/gwYMr28925JFHVn4+5JBDctddd+W6667LeuutV1nes2fPDBkyJEnStWvXnH/++Rk1alS22GKLSpvPP/88u+++e55++uk8+OCD6dix4zzrOP300zNs2LBCNQMAAHyVkejF5Pvf/35KpVJlfoMNNsjLL7+cF154IQ0aNMj6669fWbfsssumW7duGTduXJLk0EMPzSmnnJKNNtooQ4YMWeClyLMvE1+QcePGpVOnTpUAnSSrrbZaWrZsWdn3uHHjatU2u/bZPvjgg0yYMCH77rtvmjdvXplOOeWUTJgwoVAdSbLOOuvUmp85c2ZOPvnk9OjRI61atUrz5s1z1113ZfLkybXafXVEuX379pk6dWqtZb/85S/z2GOP5YEHHphvgE6SY489NtOmTatMr732WuFjAAAAEKKXAvvtt19eeeWV7LHHHhk7dmzWWWednHfeefNs37Vr15RKpSVy87AZM2YkSS655JI888wzlem5556r9d3rBfnqZee//e1vc+655+ZXv/pV7rvvvjzzzDPp169fPv3001rtvnoDslKplFmzZtVatsUWW+T111/PXXfdtcA6qqqqUl1dXWsCAAAoSoheTB577LFa848++mi6du2a1VZbLZ9//nmt9W+//XbGjx+f1VZbrbKsU6dOOfDAA3PjjTfmiCOOyCWXXJIkadSoUZIvRm5na9WqVfr165cLLrggH3zwwRy1zH4cVvfu3fPaa6/VGm194YUX8t5771X23b1797nWPlvbtm3ToUOHvPLKK1l55ZVrTSuuuOJCvUZf9tBDD2X77bfP7rvvnjXXXDMrrbRSXnrppUXq68c//nGuuuqq7LfffrnmmmsWuSYAAIAFEaIXk8mTJ+fwww/P+PHjc/XVV+e8887LYYcdlq5du2b77bfP/vvvnwcffDDPPvtsdt9993Ts2DHbb799ki++L3zXXXdl4sSJeeqpp3Lfffele/fuSZLOnTunVCrl73//e956663KyPAFF1yQmTNnZr311ssNN9yQl19+OePGjcsf/vCHyuXYm2++eXr0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xqLZcMMNM2XKlMr8YYcdlunTp2fEiBGVZa1atUqjRo3qojwAAIBvtEUaid5hhx1qTTvttFOGDh2anj175rLLLivcz6xZs3L66adnxRVXTJMmTbLmmmvm+uuvT/L/RlTvuuuu9OrVK02aNMkPfvCDTJ06NXfccUe6d++e6urq/OxnP8uHH35Y6bNv374ZNGhQBg0alJqamiy33HI54YQTUi6X51nH5MmTs/3226d58+aprq5O//798+abbyZJJk2alHr16uWJJ56otc0555yTzp07Z9asWYtc6/yO/8uvwahRo7LOOuukadOm2XDDDTN+/PgkyciRIzNs2LA8++yzlVHmq666Ku3atatMTZo0SVVVVa1ljRo1qnU5d5cuXZIkO+64Y0qlUmV+boYPH57u3buncePGWXXVVXPhhRcu+ET///79739nt912S6tWrdKsWbOss846eeyxx5L8vxH1K664Il26dElNTU123XXXvP/++0mSgQMH5v7778+5555bOdZJkybl3XffzYABA9K6des0adIkXbt2rfUHAwAAgMVpkUaiZ82atVh2fvrpp+cvf/lL/vjHP6Zr16554IEHsvvuu6d169aVNkOHDs3555+fpk2bpn///unfv3+qqqpy1VVXZcaMGdlxxx1z3nnn5Ve/+lVlmz//+c/Zd999M2bMmDzxxBM54IADssIKK2T//fef67HMDtD3339/Pv/88xx88MHZZZddMnr06HTp0iWbb755RowYkXXWWaey3YgRIzJw4MDUq/f//g6xsLXO7/j79OlT6fe4447LWWedldatW+fAAw/MPvvsk4ceeii77LJLnnvuudx555259957kyQ1NTULfR4ef/zxtGnTJiNGjMiWW26Z+vXrz7XdlVdemRNPPDHnn39+evXqlaeffjr7779/mjVrlr322mu++5gxY0b69OmTjh075tZbb027du3y1FNP1fpdmjBhQm6++eb8/e9/z7vvvpv+/fvnjDPOyKmnnppzzz03L730UtZYY42cdNJJSZLWrVvnsMMOywsvvJA77rgjyy23XP71r3/lo48+mmcdn3zyST755JPK/PTp0xfmpQIAAL7jFilEn3TSSTnyyCPTtGnTWss/+uij/Pa3v82JJ564wD4++eSTnHbaabn33nuzwQYbJElWWmmlPPjgg7n44osr39c95ZRTKpeI77vvvjn22GMzYcKErLTSSkmSn/70p7nvvvtqhehOnTrl7LPPTqlUSrdu3TJ27NicffbZcw3Ro0aNytixYzNx4sR06tQpyRfPwV599dXz+OOPZ911181+++2XAw88ML///e9TVVWVp556KmPHjs0tt9xSq6+FqXVBx//lEH3qqadW5o855phss802+fjjj9OkSZM0b948DRo0SLt27Rb4ms/L7D9atGzZcr79DBkyJGeddVZ22mmnJMmKK66YF154IRdffPECQ/RVV12Vt956K48//nhatWqVJFl55ZVrtZk1a1ZGjhyZFi1aJEn22GOPjBo1Kqeeempqamoqj1D7co2TJ09Or169Kn/gmN8oevLFHy6GDRs23zYAAADzskiXcw8bNiwzZsyYY/mHH35YOKD861//yocffpgtttgizZs3r0yXX355JkyYUGnXs2fPys9t27ZN06ZNK6F09rKpU6fW6vv73/9+SqVSZX6DDTbIyy+/nJkzZ85Rx7hx49KpU6dKgE6S1VZbLS1btsy4ceOSfHH5ev369XPTTTcl+eIy6s0222yOwLYwtRY9/q/22759+ySZ45i/bh988EEmTJiQfffdt1a9p5xyyhz1zs0zzzyTXr16VQL03HTp0qUSoJMvjnVBx3nQQQflmmuuyVprrZWjjz46Dz/88HzbH3vssZk2bVpleu211xZYOwAAwGyLNBJdLpdrhdTZnn322fmGpC+bHcJvu+22dOzYsda6qqqqSjBr2LBhZXmpVKo1P3vZ4rq8fF4aNWqUPffcMyNGjMhOO+2Uq666Kueee+4c7Ram1gUd//z6TRbfJfVFza73kksuyfrrr19r3bwu//6yJk2aLLDNopzbrbbaKq+++mpuv/323HPPPfnhD3+Ygw8+OL/73e/m2r6qqmqO1xcAAKCohQrRyyyzTOWmTqusskqtID1z5szMmDEjBx54YKG+VltttVRVVWXy5Mm1Ll2ercjo5rzMvlnVbI8++mi6du0617DXvXv3vPbaa3nttdcqo9EvvPBC3nvvvay22mqVdvvtt1/WWGONXHjhhfn8888rlzQvqgUdf1GNGjWa6wj7wmrYsOF8+2nbtm06dOiQV155JQMGDFjo/nv27Jnhw4fnnXfeKfyHlq+a17G2bt06e+21V/baa69ssskmOeqoo+YZogEAAP4XCxWizznnnJTL5eyzzz4ZNmxYrZtYzb7j8+zv9y5IixYtcuSRR+aXv/xlZs2alY033jjTpk3LQw89lOrq6nTu3HnhjuRLJk+enMMPPzw///nP89RTT+W8887LWWedNde2m2++eXr06JEBAwbknHPOyeeff55f/OIX6dOnT60biXXv3j3f//7386tf/Sr77LNPoZHV+VnQ8S/oO8azdenSJRMnTswzzzyT5ZdfPi1atFikkdYuXbpk1KhR2WijjVJVVZVllllmjjbDhg3LoYcempqammy55Zb55JNP8sQTT+Tdd9/N4YcfPt/+d9ttt5x22mnZYYcdcvrpp6d9+/Z5+umn06FDh8K/M126dMljjz2WSZMmpXnz5mnVqlWGDh2a3r17Z/XVV88nn3ySv//97+nevftCHz8AAEARCxWiZwe7FVdcMRtuuOEcl98urJNPPjmtW7fO6aefnldeeSUtW7bM2muvnV//+tf/0+XKe+65Zz766KOst956qV+/fg477LDKjcq+qlQq5ZZbbskhhxySTTfdNPXq1cuWW26Z8847b462++67bx5++OHss88+i1zbl83v+Iv6yU9+khtvvDGbbbZZ3nvvvcpdwxfWWWedlcMPPzyXXHJJOnbsmEmTJs3RZr/99kvTpk3z29/+NkcddVSaNWuWHj16ZPDgwQvsv1GjRrn77rtzxBFHZOutt87nn3+e1VZbLRdccEHhGo888sjstddeWW211fLRRx9l4sSJadSoUY499thMmjQpTZo0ySabbJJrrrlmIY4cAACguFJ5fg9QLuDjjz/Op59+WmtZdXX1/1TU/6Jv375Za621Ks9AXpxOPvnk/PWvf80///nPxd43dWP69OmpqalJp8HXpV5V0wVvwLfOpDO2qesSAABYCszOBtOmTZtvpl2ku3N/+OGHGTRoUNq0aZNmzZplmWWWqTV928yYMSPPPfdczj///BxyyCF1XQ4AAAB1ZJFC9FFHHZV//OMfueiii1JVVZXhw4dn2LBh6dChQy6//PLFXWOdGzRoUHr37p2+ffsutku5v21OO+20Wo+++vK01VZb1XV5AAAAi8UiXc69wgor5PLLL0/fvn1TXV2dp556KiuvvHKuuOKKXH311bn99tu/jlpZir3zzjt555135rquSZMmczzGa2nhcm5czg0AQFL8cu5Fek70O++8k5VWWinJF99/nh2eNt544xx00EGL0iXfcK1atVrkR1cBAAB8UyzS5dwrrbRSJk6cmCRZddVVc9111yVJ/va3v6Vly5aLrTgAAABYmixSiN57773z7LPPJkmOOeaYXHDBBWncuHF++ctf5qijjlqsBQIAAMDSYpEu5/7lL39Z+XnzzTfPiy++mCeffDIrr7xyevbsudiKAwAAgKXJIoXoL/v444/TuXPndO7ceXHUAwAAAEutRbqce+bMmTn55JPTsWPHNG/ePK+88kqS5IQTTsill166WAsEAACApcUihehTTz01I0eOzJlnnplGjRpVlq+xxhoZPnz4YisOAAAAliaLFKIvv/zy/OlPf8qAAQNSv379yvI111wzL7744mIrDgAAAJYmixSiX3/99ay88spzLJ81a1Y+++yz/7koAAAAWBotUohebbXV8n//939zLL/++uvTq1ev/7koAAAAWBot0t25TzzxxOy11155/fXXM2vWrNx4440ZP358Lr/88vz9739f3DUCAADAUmGhRqJfeeWVlMvlbL/99vnb3/6We++9N82aNcuJJ56YcePG5W9/+1u22GKLr6tWAAAAqFMLNRLdtWvXTJkyJW3atMkmm2ySVq1aZezYsWnbtu3XVR8AAAAsNRZqJLpcLteav+OOO/LBBx8s1oIAAABgabVINxab7auhGgAAAL7NFipEl0qllEqlOZYBAADAd8FCfSe6XC5n4MCBqaqqSpJ8/PHHOfDAA9OsWbNa7W688cbFVyEAAAAsJRYqRO+111615nfffffFWgwAAAAszRYqRI8YMeLrqgMAAACWev/TjcUAAADgu0SIBgAAgIKEaAAAAChIiAYAAICChGgAAAAoSIgGAACAgoRoAAAAKEiIBgAAgIKEaAAAAChIiAYAAICChGgAAAAoSIgGAACAgoRoAAAAKEiIBgAAgIKEaAAAAChIiAYAAICChGgAAAAoqEFdFwBLg+eG9Ut1dXVdlwEAACzljEQDAABAQUI0AAAAFCREAwAAQEFCNAAAABQkRAMAAEBBQjQAAAAUJEQDAABAQUI0AAAAFCREAwAAQEFCNAAAABQkRAMAAEBBQjQAAAAUJEQDAABAQUI0AAAAFCREAwAAQEFCNAAAABQkRAMAAEBBQjQAAAAUJEQDAABAQUI0AAAAFCREAwAAQEFCNAAAABQkRAMAAEBBDeq6AFgarDHkrtSralrXZSRJJp2xTV2XAAAAzIORaAAAAChIiAYAAICChGgAAAAoSIgGAACAgoRoAAAAKEiIBgAAgIKEaAAAAChIiAYAAICChGgAAAAoSIgGAACAgoRoAAAAKEiIBgAAgIKEaAAAAChIiAYAAICChGgAAAAoSIgGAACAgoRoAAAAKEiIBgAAgIKEaAAAAChIiAYAAICChGgAAAAoSIgGAACAgoRoAAAAKEiIBgAAgIKEaAAAAChIiAYAAICChGgAAAAoSIgGAACAgoRoAAAAKEiIBgAAgIKEaAAAAChIiAYAAICChGgAAAAoSIgGAACAgoRoAAAAKEiIBgAAgIKEaAAAAChIiAYAAICChGgAAAAoSIgGAACAgoTopUjfvn0zePDgui4DAACAeRCilyI33nhjTj755EJtJ02alFKplGeeeebrLaqgUqmUm2++udaykSNHplQqpVQqpV69emnfvn122WWXTJ48eaH6Hjp0aNZaa63FVywAAMAiEqKXIq1atUqLFi2W+H4/++yzr63v6urqTJkyJa+//npuuOGGjB8/PjvvvPPXtj8AAICvkxC9FPny5dxdunTJaaedln322SctWrTICiuskD/96U+VtiuuuGKSpFevXimVSunbt29l3fDhw9O9e/c0btw4q666ai688MLKutkj2Ndee2369OmTxo0b58orr1zgdp9++mkGDRqU9u3bp3HjxuncuXNOP/30Sq1JsuOOO6ZUKlXmky9GqNu1a5f27dtnww03zL777psxY8Zk+vTplTa/+tWvssoqq6Rp06ZZaaWVcsIJJ1SC/ciRIzNs2LA8++yzlVHtkSNHJknee++97LfffmndunWqq6vzgx/8IM8+++z/dhIAAADmo0FdF8C8nXXWWTn55JPz61//Otdff30OOuig9OnTJ926dcuYMWOy3nrr5d57783qq6+eRo0aJUmuvPLKnHjiiTn//PPTq1evPP3009l///3TrFmz7LXXXpW+jznmmJx11lnp1atXJUjPb7s//OEPufXWW3PddddlhRVWyGuvvZbXXnstSfL444+nTZs2GTFiRLbccsvUr19/rsczderU3HTTTalfv36tNi1atMjIkSPToUOHjB07Nvvvv39atGiRo48+Orvsskuee+653Hnnnbn33nuTJDU1NUmSnXfeOU2aNMkdd9yRmpqaXHzxxfnhD3+Yl156Ka1atZprDZ988kk++eSTyvyXwzwAAMCCCNFLsa233jq/+MUvknwxWnv22WfnvvvuS7du3dK6deskybLLLpt27dpVthkyZEjOOuus7LTTTkm+GLF+4YUXcvHFF9cK0YMHD660KbLd5MmT07Vr12y88cYplUrp3LlzZdvZtbRs2bJWLUkybdq0NG/ePOVyOR9++GGS5NBDD02zZs0qbY4//vjKz126dMmRRx6Za665JkcffXSaNGmS5s2bp0GDBrX6fvDBBzNmzJhMnTo1VVVVSZLf/e53ufnmm3P99dfngAMOmOtrevrpp2fYsGHzf+EBAADmQYheivXs2bPy8+zLoqdOnTrP9h988EEmTJiQfffdN/vvv39l+eeff14ZvZ1tnXXWWajtBg4cmC222CLdunXLlltumW233TY/+tGPFngMLVq0yFNPPZXPPvssd9xxR6688sqceuqptdpce+21+cMf/pAJEyZkxowZ+fzzz1NdXT3ffp999tnMmDEjyy67bK3lH330USZMmDDP7Y499tgcfvjhlfnp06enU6dOCzwOAACARIheqjVs2LDWfKlUyqxZs+bZfsaMGUmSSy65JOuvv36tdV+9xPrLI8FFtlt77bUzceLE3HHHHbn33nvTv3//bL755rn++uvnewz16tXLyiuvnCTp3r17JkyYkIMOOihXXHFFkuSRRx7JgAEDMmzYsPTr1y81NTW55pprctZZZ8233xkzZqR9+/YZPXr0HOtatmw5z+2qqqoqI9cAAAALS4j+hpr9HeiZM2dWlrVt2zYdOnTIK6+8kgEDBhTuq+h21dXV2WWXXbLLLrvkpz/9abbccsu88847adWqVRo2bFirlnk55phj8r3vfS+//OUvs/baa+fhhx9O586dc9xxx1XavPrqq3Mc61f7XnvttfPGG2+kQYMGtW5kBgAA8HUSor+h2rRpkyZNmuTOO+/M8ssvn8aNG6empibDhg3LoYcempqammy55Zb55JNP8sQTT+Tdd9+tdRnzVy1ou9///vdp3759evXqlXr16uWvf/1r2rVrVxn17dKlS0aNGpWNNtooVVVVWWaZZea6n06dOmXHHXfMiSeemL///e/p2rVrJk+enGuuuSbrrrtubrvtttx00021tunSpUsmTpyYZ555Jssvv3xatGiRzTffPBtssEF22GGHnHnmmVlllVXyn//8J7fddlt23HHHWperAwAALC4ecfUN1aBBg/zhD3/IxRdfnA4dOmT77bdPkuy3334ZPnx4RowYkR49eqRPnz4ZOXJk5ZFY87Kg7Vq0aJEzzzwz66yzTtZdd91MmjQpt99+e+rV++JX6Kyzzso999yTTp06pVevXvPd1y9/+cvcdtttGTNmTH784x/nl7/8ZQYNGpS11lorDz/8cE444YRa7X/yk59kyy23zGabbZbWrVvn6quvTqlUyu23355NN900e++9d1ZZZZXsuuuuefXVV9O2bdtFfVkBAADmq1Qul8t1XQTUlenTp6empiadBl+XelVN67qcJMmkM7ap6xIAAOA7Z3Y2mDZt2nxvdGwkGgAAAAoSogEAAKAgIRoAAAAKEqIBAACgICEaAAAAChKiAQAAoCAhGgAAAAoSogEAAKAgIRoAAAAKEqIBAACgICEaAAAAChKiAQAAoCAhGgAAAAoSogEAAKAgIRoAAAAKEqIBAACgICEaAAAAChKiAQAAoCAhGgAAAAoSogEAAKAgIRoAAAAKEqIBAACgICEaAAAAChKiAQAAoCAhGgAAAAoSogEAAKAgIRoAAAAKEqIBAACgICEaAAAAChKiAQAAoCAhGgAAAAoSogEAAKAgIRoAAAAKEqIBAACgICEaAAAAChKiAQAAoCAhGgAAAAoSogEAAKAgIRoAAAAKEqIBAACgoAZ1XQAsDZ4b1i/V1dV1XQYAALCUMxINAAAABQnRAAAAUJAQDQAAAAUJ0QAAAFCQEA0AAAAFCdEAAABQkBANAAAABQnRAAAAUJAQDQAAAAUJ0QAAAFCQEA0AAAAFCdEAAABQkBANAAAABQnRAAAAUJAQDQAAAAUJ0QAAAFCQEA0AAAAFCdEAAABQkBANAAAABQnRAAAAUJAQDQAAAAUJ0QAAAFBQg7ouAJYGawy5K/Wqms5z/aQztlmC1QAAAEsrI9EAAABQkBANAAAABQnRAAAAUJAQDQAAAAUJ0QAAAFCQEA0AAAAFCdEAAABQkBANAAAABQnRAAAAUJAQDQAAAAUJ0QAAAFCQEA0AAAAFCdEAAABQkBANAAAABQnRAAAAUJAQDQAAAAUJ0QAAAFCQEA0AAAAFCdEAAABQkBANAAAABQnRAAAAUJAQDQAAAAUJ0QAAAFCQEA0AAAAFCdEAAABQkBANAAAABQnRAAAAUJAQDQAAAAUJ0QAAAFCQEA0AAAAFCdEAAABQkBANAAAABQnRAAAAUJAQDQAAAAUJ0QAAAFCQEA0AAAAFCdEAAABQkBANAAAABQnRAAAAUJAQDQAAAAUJ0QAAAFCQEP0dNHr06JRKpbz33nvzbdelS5ecc845S6QmAACAbwIh+jugb9++GTx4cGV+ww03zJQpU1JTU5MkGTlyZFq2bFk3xRU0adKklEqlPPPMM3VdCgAA8B3WoK4LYMlr1KhR2rVrV9dlAAAAfOMYif6WGzhwYO6///6ce+65KZVKKZVKGTlyZOVy7tGjR2fvvffOtGnTKuuHDh06177ee++97LfffmndunWqq6vzgx/8IM8++2zhWv72t79l3XXXTePGjbPccstlxx13rKzr0qVLTjvttOyzzz5p0aJFVlhhhfzpT3+qrF9xxRWTJL169UqpVErfvn2TfHFp+nrrrZdmzZqlZcuW2WijjfLqq68u/AsFAABQgBD9LXfuuedmgw02yP77758pU6ZkypQp6dSpU2X9hhtumHPOOSfV1dWV9UceeeRc+9p5550zderU3HHHHXnyySez9tpr54c//GHeeeedBdZx2223Zccdd8zWW2+dp59+OqNGjcp6661Xq81ZZ52VddZZJ08//XR+8Ytf5KCDDsr48eOTJGPGjEmS3HvvvZkyZUpuvPHGfP7559lhhx3Sp0+f/POf/8wjjzySAw44IKVSaZ51fPLJJ5k+fXqtCQAAoCiXc3/L1dTUpFGjRmnatGnlEu4XX3yxsr5Ro0apqalJqVSa7yXeDz74YMaMGZOpU6emqqoqSfK73/0uN998c66//voccMAB863j1FNPza677pphw4ZVlq255pq12my99db5xS9+kST51a9+lbPPPjv33XdfunXrltatWydJll122Uqd77zzTqZNm5Ztt9023/ve95Ik3bt3n28dp59+eq0aAAAAFoaRaAp59tlnM2PGjCy77LJp3rx5ZZo4cWImTJiwwO2feeaZ/PCHP5xvm549e1Z+nh3qp06dOs/2rVq1ysCBA9OvX79st912OffcczNlypT57uPYY4/NtGnTKtNrr722wNoBAABmMxJNITNmzEj79u0zevToOdYVubN3kyZNFtimYcOGteZLpVJmzZo1321GjBiRQw89NHfeeWeuvfbaHH/88bnnnnvy/e9/f67tq6qqKiPpAAAAC8tI9HdAo0aNMnPmzEVenyRrr7123njjjTRo0CArr7xyrWm55ZZbYA09e/bMqFGjFrr2L9eYZK519urVK8cee2wefvjhrLHGGrnqqqsWeT8AAADzI0R/B3Tp0iWPPfZYJk2alP/+979zjO526dIlM2bMyKhRo/Lf//43H3744Rx9bL755tlggw2yww475O67786kSZPy8MMP57jjjssTTzyxwBqGDBmSq6++OkOGDMm4ceMyduzY/OY3vyl8DG3atEmTJk1y55135s0338y0adMyceLEHHvssXnkkUfy6quv5u67787LL7+8wO9FAwAALCoh+jvgyCOPTP369bPaaquldevWmTx5cq31G264YQ488MDssssuad26dc4888w5+iiVSrn99tuz6aabZu+9984qq6ySXXfdNa+++mratm27wBr69u2bv/71r7n11luz1lpr5Qc/+EHljttFNGjQIH/4wx9y8cUXp0OHDtl+++3TtGnTvPjii/nJT36SVVZZJQcccEAOPvjg/PznPy/cLwAAwMIolcvlcl0XAXVl+vTpqampSafB16VeVdN5tpt0xjZLsCoAAGBJm50Npk2blurq6nm2MxINAAAABQnRLBarr756rUdffXm68sor67o8AACAxcIjrlgsbr/99nz22WdzXVfkO9MAAADfBEI0i0Xnzp3rugQAAICvncu5AQAAoCAhGgAAAAoSogEAAKAgIRoAAAAKEqIBAACgICEaAAAAChKiAQAAoCAhGgAAAAoSogEAAKAgIRoAAAAKEqIBAACgICEaAAAAChKiAQAAoCAhGgAAAAoSogEAAKAgIRoAAAAKEqIBAACgICEaAAAAChKiAQAAoCAhGgAAAAoSogEAAKAgIRoAAAAKEqIBAACgICEaAAAAChKiAQAAoCAhGgAAAAoSogEAAKAgIRoAAAAKEqIBAACgICEaAAAAChKiAQAAoCAhGgAAAAoSogEAAKAgIRoAAAAKEqIBAACgICEaAAAACmpQ1wXA0uC5Yf1SXV1d12UAAABLOSPRAAAAUJAQDQAAAAUJ0QAAAFCQEA0AAAAFCdEAAABQkBANAAAABQnRAAAAUJAQDQAAAAUJ0QAAAFCQEA0AAAAFCdEAAABQkBANAAAABQnRAAAAUJAQDQAAAAUJ0QAAAFCQEA0AAAAFCdEAAABQkBANAAAABQnRAAAAUJAQDQAAAAUJ0QAAAFCQEA0AAAAFCdEAAABQkBANAAAABQnRAAAAUJAQDQAAAAU1qOsCoC6Vy+UkyfTp0+u4EgAAoC7NzgSzM8K8CNF8p7399ttJkk6dOtVxJQAAwNLg/fffT01NzTzXC9F8p7Vq1SpJMnny5Pm+UViypk+fnk6dOuW1115LdXV1XZfD/895WTo5L0sn52Xp5LwsnZyXpdN38byUy+W8//776dChw3zbCdF8p9Wr98VtAWpqar4z/zh8k1RXVzsvSyHnZenkvCydnJelk/OydHJelk7ftfNSZGDNjcUAAACgICEaAAAAChKi+U6rqqrKkCFDUlVVVdel8CXOy9LJeVk6OS9LJ+dl6eS8LJ2cl6WT8zJvpfKC7t8NAAAAJDESDQAAAIUJ0QAAAFCQEA0AAAAFCdEAAABQkBDNt94FF1yQLl26pHHjxll//fUzZsyY+bb/61//mlVXXTWNGzdOjx49cvvtty+hSr9bFua8jBw5MqVSqdbUuHHjJVjtt98DDzyQ7bbbLh06dEipVMrNN9+8wG1Gjx6dtddeO1VVVVl55ZUzcuTIr73O75qFPS+jR4+e471SKpXyxhtvLJmCvyNOP/30rLvuumnRokXatGmTHXbYIePHj1/gdj5fvl6Lcl58vnz9LrroovTs2TPV1dWprq7OBhtskDvuuGO+23ivfP0W9rx4r9QmRPOtdu211+bwww/PkCFD8tRTT2XNNddMv379MnXq1Lm2f/jhh7Pbbrtl3333zdNPP50ddtghO+ywQ5577rklXPm328KelySprq7OlClTKtOrr766BCv+9vvggw+y5ppr5oILLijUfuLEidlmm22y2Wab5ZlnnsngwYOz33775a677vqaK/1uWdjzMtv48eNrvV/atGnzNVX43XT//ffn4IMPzqOPPpp77rknn332WX70ox/lgw8+mOc2Pl++fotyXhKfL1+35ZdfPmeccUaefPLJPPHEE/nBD36Q7bffPs8///xc23uvLBkLe14S75VayvAttt5665UPPvjgyvzMmTPLHTp0KJ9++ulzbd+/f//yNttsU2vZ+uuvX/75z3/+tdb5XbOw52XEiBHlmpqaJVQdSco33XTTfNscffTR5dVXX73Wsl122aXcr1+/r7Gy77Yi5+W+++4rJym/++67S6QmvjB16tRykvL9998/zzY+X5a8IufF50vdWGaZZcrDhw+f6zrvlbozv/PivVKbkWi+tT799NM8+eST2XzzzSvL6tWrl8033zyPPPLIXLd55JFHarVPkn79+s2zPQtvUc5LksyYMSOdO3dOp06dFviXUr5+3itLt7XWWivt27fPFltskYceeqiuy/nWmzZtWpKkVatW82zjPbPkFTkvic+XJWnmzJm55ppr8sEHH2SDDTaYaxvvlSWvyHlJvFe+TIjmW+u///1vZs6cmbZt29Za3rZt23l+P/CNN95YqPYsvEU5L926dctll12WW265JX/5y18ya9asbLjhhvn3v/+9JEpmLub1Xpk+fXo++uijOqqK9u3b549//GNuuOGG3HDDDenUqVP69u2bp556qq5L+9aaNWtWBg8enI022ihrrLHGPNv5fFmyip4Xny9LxtixY9O8efNUVVXlwAMPzE033ZTVVlttrm29V5achTkv3iu1NajrAgAWZIMNNqj1l9ENN9ww3bt3z8UXX5yTTz65DiuDpUu3bt3SrVu3yvyGG26YCRMm5Oyzz84VV1xRh5V9ex188MF57rnn8uCDD9Z1KXxJ0fPi82XJ6NatW5555plMmzYt119/ffbaa6/cf//98wxsLBkLc168V2oTovnWWm655VK/fv28+eabtZa/+eabadeu3Vy3adeu3UK1Z+Etynn5qoYNG6ZXr17517/+9XWUSAHzeq9UV1enSZMmdVQVc7PeeusJeF+TQYMG5e9//3seeOCBLL/88vNt6/NlyVmY8/JVPl++Ho0aNcrKK6+cJOndu3cef/zxnHvuubn44ovnaOu9suQszHn5qu/6e8Xl3HxrNWrUKL17986oUaMqy2bNmpVRo0bN8/seG2ywQa32SXLPPffM9/shLJxFOS9fNXPmzIwdOzbt27f/uspkAbxXvjmeeeYZ75XFrFwuZ9CgQbnpppvyj3/8IyuuuOICt/Ge+fotynn5Kp8vS8asWbPyySefzHWd90rdmd95+arv/Hulru9sBl+na665plxVVVUeOXJk+YUXXigfcMAB5ZYtW5bfeOONcrlcLu+xxx7lY445ptL+oYceKjdo0KD8u9/9rjxu3LjykCFDyg0bNiyPHTu2rg7hW2lhz8uwYcPKd911V3nChAnlJ598srzrrruWGzduXH7++efr6hC+dd5///3y008/XX766afLScq///3vy08//XT51VdfLZfL5fIxxxxT3mOPPSrtX3nllXLTpk3LRx11VHncuHHlCy64oFy/fv3ynXfeWVeH8K20sOfl7LPPLt98883ll19+uTx27NjyYYcdVq5Xr1753nvvratD+FY66KCDyjU1NeXRo0eXp0yZUpk+/PDDShufL0veopwXny9fv2OOOaZ8//33lydOnFj+5z//WT7mmGPKpVKpfPfdd5fLZe+VurKw58V7pTYhmm+98847r7zCCiuUGzVqVF5vvfXKjz76aGVdnz59ynvttVet9tddd115lVVWKTdq1Ki8+uqrl2+77bYlXPF3w8Kcl8GDB1fatm3btrz11luXn3rqqTqo+ttr9qORvjrNPg977bVXuU+fPnNss9Zaa5UbNWpUXmmllcojRoxY4nV/2y3sefnNb35T/t73vldu3LhxuVWrVuW+ffuW//GPf9RN8d9iczsnSWq9B3y+LHmLcl58vnz99tlnn3Lnzp3LjRo1Krdu3br8wx/+sBLUymXvlbqysOfFe6W2UrlcLi+5cW8AAAD45vKdaAAAAChIiAYAAICChGgAAAAoSIgGAACAgoRoAAAAKEiIBgAAgIKEaAAAAChIiAYAAKBOPPDAA9luu+3SoUOHlEql3HzzzV/r/oYOHZpSqVRrWnXVVReqDyEaAACAOvHBBx9kzTXXzAUXXLDE9rn66qtnypQplenBBx9cqO2FaABgiRk4cGB22GGHui5jriZNmpRSqZRnnnmmrksB+M7Yaqutcsopp2THHXec6/pPPvkkRx55ZDp27JhmzZpl/fXXz+jRo/+nfTZo0CDt2rWrTMstt9xCbS9EAwDfeZ9++mldlwDAXAwaNCiPPPJIrrnmmvzzn//MzjvvnC233DIvv/zyIvf58ssvp0OHDllppZUyYMCATJ48eaG2F6IBgDrRt2/fHHLIIRk8eHCWWWaZtG3bNpdcckk++OCD7L333mnRokVWXnnl3HHHHZVtRo8enVKplNtuuy09e/ZM48aN8/3vfz/PPfdcrb5vuOGGrL766qmqqkqXLl1y1lln1VrfpUuXnHzyydlzzz1TXV2dAw44ICuuuGKSpFevXimVSunbt2+S5PHHH88WW2yR5ZZbLjU1NenTp0+eeuqpWv2VSqUMHz48O+64Y5o2bZquXbvm1ltvrdXm+eefz7bbbpvq6uq0aNEim2yySSZMmFBZP3z48HTv3j2NGzfOqquumgsvvPB/fo0BvskmT56cESNG5K9//Ws22WSTfO9738uRRx6ZjTfeOCNGjFikPtdff/2MHDkyd955Zy666KJMnDgxm2yySd5///3CfQjRAECd+fOf/5zlllsuY8aMySGHHJKDDjooO++8czbccMM89dRT+dGPfpQ99tgjH374Ya3tjjrqqJx11ll5/PHH07p162y33Xb57LPPkiRPPvlk+vfvn1133TVjx47N0KFDc8IJJ2TkyJG1+vjd736XNddcM08//XROOOGEjBkzJkly7733ZsqUKbnxxhuTJO+//3722muvPPjgg3n00UfTtWvXbL311nP8h2vYsGHp379//vnPf2brrbfOgAED8s477yRJXn/99Wy66aapqqrKP/7xjzz55JPZZ5998vnnnydJrrzyypx44ok59dRTM27cuJx22mk54YQT8uc//3mxv+YA3xRjx47NzJkzs8oqq6R58+aV6f7776/8EfLFF1+c40ZhX52OOeaYSp9bbbVVdt555/Ts2TP9+vXL7bffnvfeey/XXXdd4bpK5XK5vNiPFgBgLgYOHJj33nsvN998c/r27ZuZM2fm//7v/5IkM2fOTE1NTXbaaadcfvnlSZI33ngj7du3zyOPPJLvf//7GT16dDbbbLNcc8012WWXXZIk77zzTpZffvmMHDky/fv3z4ABA/LWW2/l7rvvruz36KOPzm233Zbnn38+yRcj0b169cpNN91UaTNp0qSsuOKKefrpp7PWWmvN8xhmzZqVli1b5qqrrsq2226b5IuR6OOPPz4nn3xyki9ulNO8efPccccd2XLLLfPrX/8611xzTcaPH5+GDRvO0efKK6+ck08+Obvttltl2SmnnJLbb789Dz/88KK81ADfOKVSKTfddFPl3hnXXnttBgwYkOeffz7169ev1bZ58+Zp165dPv3007zyyivz7XfZZZdN69at57l+3XXXzeabb57TTz+9UJ0NCrUCAPga9OzZs/Jz/fr1s+yyy6ZHjx6VZW3btk2STJ06tdZ2G2ywQeXnVq1apVu3bhk3blySZNy4cdl+++1rtd9oo41yzjnnZObMmZX/iK2zzjqFanzzzTdz/PHHZ/To0Zk6dWpmzpyZDz/8cI7v0H35WJo1a5bq6upK3c8880w22WSTuQboDz74IBMmTMi+++6b/fffv7L8888/T01NTaEaAb6NevXqlZkzZ2bq1KnZZJNN5tqmUaNGC/2Iqi+bMWNGJkyYkD322KPwNkI0AFBnvhoqS6VSrWWlUinJF6O/i1uzZs0Ktdtrr73y9ttv59xzz03nzp1TVVWVDTbYYI6bkc3tWGbX3aRJk3n2P2PGjCTJJZdckvXXX7/Wuq+OvAB828yYMSP/+te/KvMTJ07MM888k1atWmWVVVbJgAEDsueee+ass85Kr1698tZbb2XUqFHp2bNnttlmm4Xe35FHHpntttsunTt3zn/+858MGTIk9evXr3Ul0III0QDAN86jjz6aFVZYIUny7rvv5qWXXkr37t2TJN27d89DDz1Uq/1DDz2UVVZZZb6htFGjRkm+uKz8q9teeOGF2XrrrZMkr732Wv773/8uVL09e/bMn//853z22WdzhO22bdumQ4cOeeWVVzJgwICF6hfgm+6JJ57IZpttVpk//PDDk3zxB8yRI0dmxIgROeWUU3LEEUfk9ddfz3LLLZfvf//7la/TLKx///vf2W233fL222+ndevW2XjjjfPoo4/O93LvrxKiAYBvnJNOOinLLrts2rZtm+OOOy7LLbdc5Tt0RxxxRNZdd92cfPLJ2WWXXfLII4/k/PPPX+Ddrtu0aZMmTZrkzjvvzPLLL5/GjRunpqYmXbt2zRVXXJF11lkn06dPz1FHHTXfkeW5GTRoUM4777zsuuuuOfbYY1NTU5NHH3006623Xrp165Zhw4bl0EMPTU1NTbbccst88skneeKJJ/Luu+9W/kMJ8G3Ut2/fzO82XQ0bNsywYcMybNiwxbK/a6655n/uw925AYBvnDPOOCOHHXZYevfunTfeeCN/+9vfKiPJa6+9dq677rpcc801WWONNXLiiSfmpJNOysCBA+fbZ4MGDfKHP/whF198cTp06FD5XvWll16ad999N2uvvXb22GOPHHrooWnTps1C1bvsssvmH//4R2bMmJE+ffqkd+/eueSSSyqj0vvtt1+GDx+eESNGpEePHunTp09GjhxZeewWAEsPd+cGAL4xZt+d+913303Lli3ruhwAvoOMRAMAAEBBQjQAAAAU5HJuAAAAKMhINAAAABQkRAMAAEBBQjQAAAAUJEQDAABAQUI0AAAAFCREAwAAQEFCNAAAABQkRAMAAEBB/x/2UPtanHU+SwAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 1000x800 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "from sklearn.pipeline import make_pipeline\n",
    "from sklearn.impute import SimpleImputer\n",
    "from sklearn.linear_model import LogisticRegression\n",
    "from sklearn.metrics import roc_auc_score\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "\n",
    "# 设置 Logistic Regression 参数\n",
    "logreg_params = {\n",
    "    'penalty': 'l2',  # 使用 L2 正则化\n",
    "    'C': 1.0,  # 正则化强度的倒数\n",
    "    'solver': 'lbfgs',  # 优化算法\n",
    "    'max_iter': 100,  # 最大迭代次数\n",
    "    'random_state': 1  # 随机数种子\n",
    "}\n",
    "\n",
    "# 创建一个简单的填充器，这里使用均值填补\n",
    "imputer = SimpleImputer(missing_values=np.nan, strategy='mean')\n",
    "\n",
    "# 创建 Logistic Regression 模型\n",
    "logreg_model = LogisticRegression(**logreg_params)\n",
    "\n",
    "# 创建包含填充器和逻辑回归模型的管道\n",
    "pipeline = make_pipeline(imputer, logreg_model)\n",
    "\n",
    "# 训练 Logistic Regression 模型\n",
    "pipeline.fit(x_train, y_train)\n",
    "\n",
    "# 评估模型\n",
    "valid_logreg = pipeline.predict_proba(x_train)[:, 1]\n",
    "print(\"Logistic Regression score: {:<8.8f}\".format(roc_auc_score(y_train, valid_logreg)))\n",
    "\n",
    "# 在测试集上进行预测\n",
    "predict_logreg = pipeline.predict_proba(x_test)[:, 1]\n",
    "\n",
    "# 保存预测结果\n",
    "testA = pd.read_csv(\"testA.csv\")\n",
    "testA['isDefault'] = predict_logreg\n",
    "submission_data = testA[['id', 'isDefault']]\n",
    "submission_data.to_csv(\"myresult_logreg.csv\", index=False)\n",
    "\n",
    "# 获取逻辑回归模型的系数\n",
    "feature_importance = pipeline.named_steps['logisticregression'].coef_ \n",
    "\n",
    "# 创建一个特征重要性的DataFrame\n",
    "feature_importance_df = pd.DataFrame({\n",
    "    'Feature': x_train.columns,\n",
    "    'Importance': feature_importance.flatten()  # 使用 flatten() 将系数数组转换为一维\n",
    "})\n",
    "\n",
    "# 按重要性排序\n",
    "feature_importance_df = feature_importance_df.sort_values(by='Importance', ascending=False)\n",
    "\n",
    "# 输出特征重要性\n",
    "print(\"Feature importances:\")\n",
    "print(feature_importance_df)\n",
    "\n",
    "# 绘制条形图，只显示前5个最重要的特征\n",
    "top_n = 5\n",
    "plt.figure(figsize=(10, 8))\n",
    "plt.barh(feature_importance_df.head(top_n)['Feature'], feature_importance_df.head(top_n)['Importance'])\n",
    "plt.xlabel('Importance')\n",
    "plt.ylabel('Feature')\n",
    "plt.title('Top 5 Feature Importances')\n",
    "plt.gca().invert_yaxis()  # 反转y轴，使得最重要的特征在上方\n",
    "plt.show()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
